<!DOCTYPE html>
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
  <meta name="description" content="tong.li&#39;s blog">
  <meta name="keyword" content="彤哥哥博客，95后技术爱好者,现就职于同程旅行/同程艺龙上海分公司，专注于互联网技术分享的平台。">
  
    <link rel="shortcut icon" href="/css/images/icon.png">
  
  <title>
    
      【Java并发编程实战】-解读J.U.C并发包之AQS | 彤哥哥的博客
    
  </title>
  <link href="https://cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <link href="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.css" rel="stylesheet">
  <link href="https://cdn.staticfile.org/highlight.js/9.12.0/styles/tomorrow-night.min.css" rel="stylesheet">
  
<link rel="stylesheet" href="/css/style.css">

  
  <script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
  <script src="https://cdn.staticfile.org/geopattern/1.2.3/js/geopattern.min.js"></script>
  <script src="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.js"></script>
  
    
<script src="/js/qrious.js"></script>

  
  
  
  
    <!-- MathJax support START -->
    <script type="text/x-mathjax-config">
      MathJax.Hub.Config({
        tex2jax: {
          inlineMath: [ ['$','$'], ["\\(","\\)"]  ],
          processEscapes: true,
          skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
        }
      });
    </script>

    <script type="text/x-mathjax-config">
      MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax(), i;
        for (i=0; i < all.length; i += 1) {
          all[i].SourceElement().parentNode.className += ' has-jax';
        }
      });
    </script>
    <script type="text/javascript" src="https://cdn.staticfile.org/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
    <!-- MathJax support END -->
  


  
  
    
<script src="/js/local-search.js"></script>


<meta name="generator" content="Hexo 5.4.2"></head>
<div class="wechat-share">
  <img src="/css/images/logo.png" />
</div>
  <body>
    <header class="header fixed-header">
  <div class="header-container">
    <a class="home-link" href="/">
      <div class="logo"></div>
      <span>彤哥哥的博客</span>
    </a>
    <ul class="right-list">
      
        <li class="list-item">
          
            <a href="/" class="item-link">主页</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/series/" class="item-link">分类</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/tags/" class="item-link">标签</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/archives/" class="item-link">归档</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/project/" class="item-link">项目</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/about/" class="item-link">关于</a>
          
        </li>
      
      
        <li class="menu-item menu-item-search right-list">
    <a role="button" class="popup-trigger">
        <i class="fa fa-search fa-fw"></i>
    </a>
</li>
      
    </ul>
    <div class="menu">
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
    </div>
    <div class="menu-mask">
      <ul class="menu-list">
        
          <li class="menu-item">
            
              <a href="/" class="menu-link">主页</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/series/" class="menu-link">分类</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/tags/" class="menu-link">标签</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/archives/" class="menu-link">归档</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/project/" class="menu-link">项目</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/about/" class="menu-link">关于</a>
            
          </li>
        
      </ul>
    </div>
    
      <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
            <span class="search-icon">
                <i class="fa fa-search"></i>
            </span>
            <div class="search-input-container">
                <input autocomplete="off" autocapitalize="off"
                    placeholder="Please enter your keyword(s) to search." spellcheck="false"
                    type="search" class="search-input">
            </div>
            <span class="popup-btn-close">
                <i class="fa fa-times-circle"></i>
            </span>
        </div>
        <div id="search-result">
            <div id="no-result">
                <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
            </div>
        </div>
    </div>
</div>
    
  </div>
</header>

    <div id="article-banner">
  <h2>【Java并发编程实战】-解读J.U.C并发包之AQS</h2>
  <p class="post-date">2020-07-22</p>
  <div class="arrow-down">
    <a href="javascript:;"></a>
  </div>
</div>
<main class="app-body flex-box">
  <!-- Article START -->
  <article class="post-article">
    <section class="markdown-content"><h1 id="1-AQS介绍"><a href="#1-AQS介绍" class="headerlink" title="1. AQS介绍"></a>1. AQS介绍</h1><h2 id="1-1-简要说明"><a href="#1-1-简要说明" class="headerlink" title="1.1 简要说明"></a>1.1 简要说明</h2><p>所谓的AQS，其实指的是Java并发包(java.util.concurrent)中的抽象类AbstractQueuedSynchronizer。</p>
<p>AQS的核心是一个线程等待队列，采用的是一个先进先出FIFO队列。它可以用于构建锁或者其他相关同步的基础框架。</p>
<p>Java并发包下的ThreadPoolExecutor.Worker、Semaphore、CountDownLatch、ReentrantLock、ReentrantReadWriteLock都是基于AQS来实现的。因此AQS是学习并发包重要武器。</p>
<p>我们打开源码，通读一下文档注释:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 提供一个基于先进先出(FIFO)等待队列实现的阻塞锁和相关同步器(semaphores,events等)的框架。</span></span><br><span class="line"><span class="comment"> * 该类的设计为大多数类型的同步器提供了有用的基础,这些同步器依赖于单个原子int值来表示状态(state)。</span></span><br><span class="line"><span class="comment"> * 子类必须定义更改此状态的protected方法，以及根据该对象被获取或释放来定义该状态的含义。</span></span><br><span class="line"><span class="comment"> * 鉴于这些,这个类中的其他方法执行所有排队和阻塞机制。子类可以保持其他状态字段,但只能以原子方式更新。</span></span><br><span class="line"><span class="comment"> * 使用getState()、setState(int)和compareAndSetState(int, int)来保持同步化。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 子类应定义为非公共内部帮助类，用于实现其外部类的同步属性。</span></span><br><span class="line"><span class="comment"> * AbstractQueuedSynchronizer类不实现任何同步接口。</span></span><br><span class="line"><span class="comment"> * 相反,它定义了一些方法,如acquireInterruptibly(int),</span></span><br><span class="line"><span class="comment"> * 可以通过具体的锁和相关同步器来调用适当执行其public方法。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 此类默认支持互斥模式(exclusive mode-互斥锁)和共享模式(shared mode-共享锁)。</span></span><br><span class="line"><span class="comment"> * 当获以互斥模式获取时,其他线程尝试获取是无法成功成功的。</span></span><br><span class="line"><span class="comment"> * 由多个线程获取的共享模式可能(但不一定)成功。</span></span><br><span class="line"><span class="comment"> * 除了在机制意义上，这个类不理解这些差异，当共享模式获取成功时,</span></span><br><span class="line"><span class="comment"> * 下一个等待线程(如果存在)也必须确定它是否也可以获取。</span></span><br><span class="line"><span class="comment"> * 在不同模式下等待的线程共享相同的FIFO队列。通常,实现子类只支持这些模式之一,</span></span><br><span class="line"><span class="comment"> * 但是两者都可以在ReadWriteLock中发挥作用。</span></span><br><span class="line"><span class="comment"> * 仅支持互斥或仅共享模式的子类不需要定义支持未使用模式的方法。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 该类为内部队列提供检查,检测和监控方法,以及条件对象的类似方法。</span></span><br><span class="line"><span class="comment"> * 这些可以根据需要导出到类中，使用AbstractQueuedSynchronizer进行同步机制。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 此类的序列化仅存储底层的原子整数维护状态，因此反序列化的对象具有空的线程队列。</span></span><br><span class="line"><span class="comment"> * 需要序列化性的典型子类将定义一个readObject方法，该方法可在反序列化时将其恢复为已知的初始状态。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 用法:</span></span><br><span class="line"><span class="comment"> * 使用这个类用作同步的基础上，重新定义以下方法，如适用，通过检查和或修改使用所述同步状态getState()、setState(int)、compareAndSetState(int, int) ：</span></span><br><span class="line"><span class="comment"> *  tryAcquire(int)</span></span><br><span class="line"><span class="comment"> *  tryRelease(int)</span></span><br><span class="line"><span class="comment"> *  tryAcquireShared(int)</span></span><br><span class="line"><span class="comment"> *  tryReleaseShared(int)</span></span><br><span class="line"><span class="comment"> *  isHeldExclusively()</span></span><br><span class="line"><span class="comment"> * 每个这些方法默认抛出UnsupportedOperationException。</span></span><br><span class="line"><span class="comment"> * 这些方法的实现必须是线程安全的，通常应该是短暂的而不是阻塞的。</span></span><br><span class="line"><span class="comment"> * 定义这些方法是唯一支持使用此类的方法。</span></span><br><span class="line"><span class="comment"> * 所有其他方法都被声明为final ，因为它们不能独立变化。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 即使这个类基于内部FIFO队列，它也不会自动执行FIFO采集策略。 </span></span><br><span class="line"><span class="comment"> * 排他同步的核心形式如下：</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * Acquire:</span></span><br><span class="line"><span class="comment"> *     while (!tryAcquire(arg)) &#123;</span></span><br><span class="line"><span class="comment"> *        enqueue thread if it is not already queued;</span></span><br><span class="line"><span class="comment"> *        possibly block current thread;</span></span><br><span class="line"><span class="comment"> *     &#125;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * Release:</span></span><br><span class="line"><span class="comment"> *     if (tryRelease(arg))</span></span><br><span class="line"><span class="comment"> *        unblock the first queued thread;</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@since</span> 1.5</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> Doug Lea</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure>

<h2 id="1-2-继承体系"><a href="#1-2-继承体系" class="headerlink" title="1.2 继承体系"></a>1.2 继承体系</h2><h3 id="1-2-1-继承体系图"><a href="#1-2-1-继承体系图" class="headerlink" title="1.2.1 继承体系图"></a>1.2.1 继承体系图</h3><p><img src="https://ltyeamin.github.io/imgs/2020/07/20200731161220.png" alt="AQS继承体系图"></p>
<h3 id="1-2-2-AbstractOwnableSynchronizer顶层抽象"><a href="#1-2-2-AbstractOwnableSynchronizer顶层抽象" class="headerlink" title="1.2.2 AbstractOwnableSynchronizer顶层抽象"></a>1.2.2 AbstractOwnableSynchronizer顶层抽象</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> java.util.concurrent.locks;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 可能是线程专有的同步器。</span></span><br><span class="line"><span class="comment"> * 此类为创建可能涉及所有概念的锁和相关的同步器提供了基础。</span></span><br><span class="line"><span class="comment"> * AbstractOwnableSynchronizer类本身不管理或使用此信息。</span></span><br><span class="line"><span class="comment"> * 然而，子类和工具可能会使用适当维护的值来帮助控制和监视访问并提供诊断。</span></span><br><span class="line"><span class="comment"> * A synchronizer that may be exclusively owned by a thread.  This</span></span><br><span class="line"><span class="comment"> * class provides a basis for creating locks and related synchronizers</span></span><br><span class="line"><span class="comment"> * that may entail a notion of ownership.  The</span></span><br><span class="line"><span class="comment"> * &#123;<span class="doctag">@code</span> AbstractOwnableSynchronizer&#125; class itself does not manage or</span></span><br><span class="line"><span class="comment"> * use this information. However, subclasses and tools may use</span></span><br><span class="line"><span class="comment"> * appropriately maintained values to help control and monitor access</span></span><br><span class="line"><span class="comment"> * and provide diagnostics.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@since</span> 1.6</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> Doug Lea</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">AbstractOwnableSynchronizer</span></span><br><span class="line">    <span class="keyword">implements</span> <span class="title class_">java</span>.io.Serializable &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** 即使所有字段都是瞬态的(不序列化)，也要使用序列号。*/</span></span><br><span class="line">    <span class="comment">/** Use serial ID even though all fields transient. */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> <span class="variable">serialVersionUID</span> <span class="operator">=</span> <span class="number">3737899427754241961L</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 供子类使用的空构造函数。</span></span><br><span class="line"><span class="comment">     * Empty constructor for use by subclasses.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="title function_">AbstractOwnableSynchronizer</span><span class="params">()</span> &#123; &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 互斥模式同步下的当前线程拥有者。</span></span><br><span class="line"><span class="comment">     * The current owner of exclusive mode synchronization.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">transient</span> Thread exclusiveOwnerThread;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 设置当前拥有互斥访问的线程。</span></span><br><span class="line"><span class="comment">     * null参数表示没有线程拥有访问权限。</span></span><br><span class="line"><span class="comment">     * 此方法不以其他方式强加任何同步或volatile字段访问。</span></span><br><span class="line"><span class="comment">     * Sets the thread that currently owns exclusive access.</span></span><br><span class="line"><span class="comment">     * A &#123;<span class="doctag">@code</span> null&#125; argument indicates that no thread owns access.</span></span><br><span class="line"><span class="comment">     * This method does not otherwise impose any synchronization or</span></span><br><span class="line"><span class="comment">     * &#123;<span class="doctag">@code</span> volatile&#125; field accesses.</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> thread the owner thread 拥有者线程</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title function_">setExclusiveOwnerThread</span><span class="params">(Thread thread)</span> &#123;</span><br><span class="line">        exclusiveOwnerThread = thread;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 返回上一次由setExclusiveOwnerThread或null设置的线程(如果从未设置)。</span></span><br><span class="line"><span class="comment">     * 否则，此方法不会强制进行任何同步或volatile字段访问。</span></span><br><span class="line"><span class="comment">     * Returns the thread last set by &#123;<span class="doctag">@code</span> setExclusiveOwnerThread&#125;,</span></span><br><span class="line"><span class="comment">     * or &#123;<span class="doctag">@code</span> null&#125; if never set.  This method does not otherwise</span></span><br><span class="line"><span class="comment">     * impose any synchronization or &#123;<span class="doctag">@code</span> volatile&#125; field accesses.</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> the owner thread 返回拥有者线程</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">final</span> Thread <span class="title function_">getExclusiveOwnerThread</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> exclusiveOwnerThread;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h1 id="2-AQS源码分析"><a href="#2-AQS源码分析" class="headerlink" title="2. AQS源码分析"></a>2. AQS源码分析</h1><h2 id="2-1-成员变量"><a href="#2-1-成员变量" class="headerlink" title="2.1 成员变量"></a>2.1 成员变量</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> java.util.concurrent.locks;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.TimeUnit;</span><br><span class="line"><span class="keyword">import</span> java.util.ArrayList;</span><br><span class="line"><span class="keyword">import</span> java.util.Collection;</span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"><span class="keyword">import</span> sun.misc.Unsafe;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">abstract</span> <span class="keyword">class</span> <span class="title class_">AbstractQueuedSynchronizer</span> <span class="keyword">extends</span> <span class="title class_">AbstractOwnableSynchronizer</span> <span class="keyword">implements</span> <span class="title class_">java</span>.io.Serializable &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** 序列化UID */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> <span class="variable">serialVersionUID</span> <span class="operator">=</span> <span class="number">7373984972572414691L</span>;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 等待队列的头,延迟初始化。除初始化外,只能通过setHead方法进行修改。</span></span><br><span class="line"><span class="comment">     * 注意: 如果head存在,则保证其waitStatus不为CANCELLED。</span></span><br><span class="line"><span class="comment">     * Head of the wait queue, lazily initialized.  Except for</span></span><br><span class="line"><span class="comment">     * initialization, it is modified only via method setHead.  Note:</span></span><br><span class="line"><span class="comment">     * If head exists, its waitStatus is guaranteed not to be</span></span><br><span class="line"><span class="comment">     * CANCELLED.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">transient</span> <span class="keyword">volatile</span> Node head;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 等待队列的尾部,延迟初始化。</span></span><br><span class="line"><span class="comment">     * 仅通过方法enq进行修改以添加新的等待节点。</span></span><br><span class="line"><span class="comment">     * Tail of the wait queue, lazily initialized.  Modified only via</span></span><br><span class="line"><span class="comment">     * method enq to add new wait node.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">transient</span> <span class="keyword">volatile</span> Node tail;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 控制加锁解锁的状态变量,用于同步状态。</span></span><br><span class="line"><span class="comment">     * The synchronization state.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">volatile</span> <span class="type">int</span> state;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 旋转超时阈值</span></span><br><span class="line"><span class="comment">     * 旋转比使用定时停驻更快的纳秒数。粗略估计足以在非常短的超时时间内提高响应能力。</span></span><br><span class="line"><span class="comment">     * The number of nanoseconds for which it is faster to spin</span></span><br><span class="line"><span class="comment">     * rather than to use timed park. A rough estimate suffices</span></span><br><span class="line"><span class="comment">     * to improve responsiveness with very short timeouts.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> <span class="variable">spinForTimeoutThreshold</span> <span class="operator">=</span> <span class="number">1000L</span>;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 设置为支持compareAndSet。我们需要在这里本地实现：</span></span><br><span class="line"><span class="comment">     * 为了允许将来的增强，我们不能显式地继承AtomicInteger的子类，否则它将是高效且有用的。</span></span><br><span class="line"><span class="comment">     * 因此,作为罪恶之源,我们使用热点内在API本机实现。</span></span><br><span class="line"><span class="comment">     * 当我们这样做时，我们会对其他可CAS字段执行相同的操作(否则可以通过原子字段更新程序来完成)。</span></span><br><span class="line"><span class="comment">     * unsafe: Unsafe类主要提供了像C语言的指针一样操作内存空间的能力，可以直接操作内存，不受JVM和GC管理。</span></span><br><span class="line"><span class="comment">     * stateOffset: 状态变量state的内存地址偏移量</span></span><br><span class="line"><span class="comment">     * headOffset: 头节点的内存地址偏移量</span></span><br><span class="line"><span class="comment">     * tailOffset: 尾节点的内存地址偏移量</span></span><br><span class="line"><span class="comment">     * waitStatusOffset: 等待状态的内存地址偏移量(Node的属性)</span></span><br><span class="line"><span class="comment">     * nextOffset: 下一个节点的内存地址偏移量(Node的属性)</span></span><br><span class="line"><span class="comment">     * Setup to support compareAndSet. We need to natively implement</span></span><br><span class="line"><span class="comment">     * this here: For the sake of permitting future enhancements, we</span></span><br><span class="line"><span class="comment">     * cannot explicitly subclass AtomicInteger, which would be</span></span><br><span class="line"><span class="comment">     * efficient and useful otherwise. So, as the lesser of evils, we</span></span><br><span class="line"><span class="comment">     * natively implement using hotspot intrinsics API. And while we</span></span><br><span class="line"><span class="comment">     * are at it, we do the same for other CASable fields (which could</span></span><br><span class="line"><span class="comment">     * otherwise be done with atomic field updaters).</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Unsafe</span> <span class="variable">unsafe</span> <span class="operator">=</span> Unsafe.getUnsafe();</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> stateOffset;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> headOffset;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> tailOffset;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> waitStatusOffset;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> nextOffset;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h2 id="2-2-静态初始化"><a href="#2-2-静态初始化" class="headerlink" title="2.2 静态初始化"></a>2.2 静态初始化</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * 静态初始化5个偏移量。</span></span><br><span class="line"><span class="comment"> * 通过反射getDeclaredField获取本类所有的字段，包括private的，但是不能获取继承来的字段。</span></span><br><span class="line"><span class="comment"> * 利用unsafe.objectFieldOffset获取当前字段相对Java对象的“起始地址”的偏移量然后并赋值。</span></span><br><span class="line"><span class="comment"> * 如果发生异常,直接抛出Error。</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">static</span> &#123;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        stateOffset = unsafe.objectFieldOffset</span><br><span class="line">            (AbstractQueuedSynchronizer.class.getDeclaredField(<span class="string">&quot;state&quot;</span>));</span><br><span class="line">        headOffset = unsafe.objectFieldOffset</span><br><span class="line">            (AbstractQueuedSynchronizer.class.getDeclaredField(<span class="string">&quot;head&quot;</span>));</span><br><span class="line">        tailOffset = unsafe.objectFieldOffset</span><br><span class="line">            (AbstractQueuedSynchronizer.class.getDeclaredField(<span class="string">&quot;tail&quot;</span>));</span><br><span class="line">        waitStatusOffset = unsafe.objectFieldOffset</span><br><span class="line">            (Node.class.getDeclaredField(<span class="string">&quot;waitStatus&quot;</span>));</span><br><span class="line">        nextOffset = unsafe.objectFieldOffset</span><br><span class="line">            (Node.class.getDeclaredField(<span class="string">&quot;next&quot;</span>));</span><br><span class="line"></span><br><span class="line">    &#125; <span class="keyword">catch</span> (Exception ex) &#123; <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">Error</span>(ex); &#125;</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>

<h2 id="2-3-构造器"><a href="#2-3-构造器" class="headerlink" title="2.3 构造器"></a>2.3 构造器</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 创建一个新的AbstractQueuedSynchronizer&#125;实例,初始同步状态(state)为零。</span></span><br><span class="line"><span class="comment"> * Creates a new &#123;<span class="doctag">@code</span> AbstractQueuedSynchronizer&#125; instance</span></span><br><span class="line"><span class="comment"> * with initial synchronization state of zero.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">protected</span> <span class="title function_">AbstractQueuedSynchronizer</span><span class="params">()</span> &#123; &#125;</span><br></pre></td></tr></table></figure>



<h2 id="2-4-重要方法"><a href="#2-4-重要方法" class="headerlink" title="2.4 重要方法"></a>2.4 重要方法</h2><h3 id="2-4-1-state的getter-setter方法"><a href="#2-4-1-state的getter-setter方法" class="headerlink" title="2.4.1 state的getter/setter方法"></a>2.4.1 state的getter/setter方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  * 返回同步状态的当前值。此操作具有volatile读取的内存语义。</span></span><br><span class="line"><span class="comment">  * Returns the current value of synchronization state.</span></span><br><span class="line"><span class="comment">  * This operation has memory semantics of a &#123;<span class="doctag">@code</span> volatile&#125; read.</span></span><br><span class="line"><span class="comment">  * <span class="doctag">@return</span> current state value 返回当前状态值</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"><span class="keyword">protected</span> <span class="keyword">final</span> <span class="type">int</span> <span class="title function_">getState</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> state;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 设置同步状态的值。此操作具有volatile写操作的内存语义。</span></span><br><span class="line"><span class="comment"> * Sets the value of synchronization state.</span></span><br><span class="line"><span class="comment"> * This operation has memory semantics of a &#123;<span class="doctag">@code</span> volatile&#125; write.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> newState the new state value 新的状态值</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">protected</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title function_">setState</span><span class="params">(<span class="type">int</span> newState)</span> &#123;</span><br><span class="line">    state = newState;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="2-4-2-compareAndSetState方法"><a href="#2-4-2-compareAndSetState方法" class="headerlink" title="2.4.2 compareAndSetState方法"></a>2.4.2 compareAndSetState方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">  * CAS(CompareAndSwap)原子操作:比较与设置state值</span></span><br><span class="line"><span class="comment">  * 如果当前状态值等于期望值，则以原子方式将同步状态的值设置为给定的新值。</span></span><br><span class="line"><span class="comment">  * 此操作具有volatile读取和写入的内存语义。</span></span><br><span class="line"><span class="comment">  * Atomically sets synchronization state to the given updated</span></span><br><span class="line"><span class="comment">  * value if the current state value equals the expected value.</span></span><br><span class="line"><span class="comment">  * This operation has memory semantics of a &#123;<span class="doctag">@code</span> volatile&#125; read</span></span><br><span class="line"><span class="comment">  * and write.</span></span><br><span class="line"><span class="comment">  *</span></span><br><span class="line"><span class="comment">  * <span class="doctag">@param</span> expect the expected value 期望值</span></span><br><span class="line"><span class="comment">  * <span class="doctag">@param</span> update the new value 新值</span></span><br><span class="line"><span class="comment">  * <span class="doctag">@return</span> &#123;<span class="doctag">@code</span> true&#125; if successful. False return indicates that the actual</span></span><br><span class="line"><span class="comment">  *         value was not equal to the expected value. 若设置成功返回true,反之返回false</span></span><br><span class="line"><span class="comment">  */</span></span><br><span class="line"><span class="keyword">protected</span> <span class="keyword">final</span> <span class="type">boolean</span> <span class="title function_">compareAndSetState</span><span class="params">(<span class="type">int</span> expect, <span class="type">int</span> update)</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> unsafe.compareAndSwapInt(<span class="built_in">this</span>, stateOffset, expect, update);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-4-3-tryAcquire方法"><a href="#2-4-3-tryAcquire方法" class="headerlink" title="2.4.3  tryAcquire方法"></a>2.4.3  tryAcquire方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 尝试以独占/互斥/排他模式进行获取锁。</span></span><br><span class="line"><span class="comment"> * 该方法应查询对象的状态是否允许以独占模式获取对象，如果是，则查询该对象。 </span></span><br><span class="line"><span class="comment"> * 此方法总是由执行获取的线程调用。如果此方法报告失败，则获取方法可以将线程排队(如果尚未排队),</span></span><br><span class="line"><span class="comment"> * 直到被其他线程释放发出信号。可以使用实现方法Lock＃tryLock()</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * Attempts to acquire in exclusive mode. This method should query</span></span><br><span class="line"><span class="comment"> * if the state of the object permits it to be acquired in the</span></span><br><span class="line"><span class="comment"> * exclusive mode, and if so to acquire it.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;This method is always invoked by the thread performing</span></span><br><span class="line"><span class="comment"> * acquire.  If this method reports failure, the acquire method</span></span><br><span class="line"><span class="comment"> * may queue the thread, if it is not already queued, until it is</span></span><br><span class="line"><span class="comment"> * signalled by a release from some other thread. This can be used</span></span><br><span class="line"><span class="comment"> * to implement method &#123;<span class="doctag">@link</span> Lock#tryLock()&#125;.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 默认的实现抛出UnsupportedOperationException,交给子类去实现</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;The default</span></span><br><span class="line"><span class="comment"> * implementation throws &#123;<span class="doctag">@link</span> UnsupportedOperationException&#125;.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> arg the acquire argument. This value is always the one</span></span><br><span class="line"><span class="comment"> *        passed to an acquire method, or is the value saved on entry</span></span><br><span class="line"><span class="comment"> *        to a condition wait.  The value is otherwise uninterpreted</span></span><br><span class="line"><span class="comment"> *        and can represent anything you like.  获取锁的参数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> &#123;<span class="doctag">@code</span> true&#125; if successful. Upon success, this object has</span></span><br><span class="line"><span class="comment"> *         been acquired.  若成功获取锁,返回true,反之返回false</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> IllegalMonitorStateException if acquiring would place this</span></span><br><span class="line"><span class="comment"> *         synchronizer in an illegal state. This exception must be</span></span><br><span class="line"><span class="comment"> *         thrown in a consistent fashion for synchronization to work</span></span><br><span class="line"><span class="comment"> *         correctly.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> UnsupportedOperationException if exclusive mode is not supported</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">protected</span> <span class="type">boolean</span> <span class="title function_">tryAcquire</span><span class="params">(<span class="type">int</span> arg)</span> &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">UnsupportedOperationException</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-4-4-tryRelease方法"><a href="#2-4-4-tryRelease方法" class="headerlink" title="2.4.4 tryRelease方法"></a>2.4.4 tryRelease方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 在互斥模式下尝试设置state来表示释放锁</span></span><br><span class="line"><span class="comment"> * Attempts to set the state to reflect a release in exclusive</span></span><br><span class="line"><span class="comment"> * mode.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 这个方法总是由正在执行的线程释放锁</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;This method is always invoked by the thread performing release.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 默认的实现抛出UnsupportedOperationException,交给子类去实现</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;The default implementation throws</span></span><br><span class="line"><span class="comment"> * &#123;<span class="doctag">@link</span> UnsupportedOperationException&#125;.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> arg the release argument. This value is always the one</span></span><br><span class="line"><span class="comment"> *        passed to a release method, or the current state value upon</span></span><br><span class="line"><span class="comment"> *        entry to a condition wait.  The value is otherwise</span></span><br><span class="line"><span class="comment"> *        uninterpreted and can represent anything you like. 释放参数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> &#123;<span class="doctag">@code</span> true&#125; if this object is now in a fully released</span></span><br><span class="line"><span class="comment"> *         state, so that any waiting threads may attempt to acquire;</span></span><br><span class="line"><span class="comment"> *         and &#123;<span class="doctag">@code</span> false&#125; otherwise. 返回true,如果此对象现在处于完全释放状态，则任何等待线程都可以尝试获取；反之返回false</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> IllegalMonitorStateException if releasing would place this</span></span><br><span class="line"><span class="comment"> *         synchronizer in an illegal state. This exception must be</span></span><br><span class="line"><span class="comment"> *         thrown in a consistent fashion for synchronization to work</span></span><br><span class="line"><span class="comment"> *         correctly.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> UnsupportedOperationException if exclusive mode is not supported</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">protected</span> <span class="type">boolean</span> <span class="title function_">tryRelease</span><span class="params">(<span class="type">int</span> arg)</span> &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">UnsupportedOperationException</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-4-5-tryAcquireShared方法"><a href="#2-4-5-tryAcquireShared方法" class="headerlink" title="2.4.5 tryAcquireShared方法"></a>2.4.5 tryAcquireShared方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 以共享模式获取锁 </span></span><br><span class="line"><span class="comment"> * Attempts to acquire in shared mode. This method should query if</span></span><br><span class="line"><span class="comment"> * the state of the object permits it to be acquired in the shared</span></span><br><span class="line"><span class="comment"> * mode, and if so to acquire it.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;This method is always invoked by the thread performing</span></span><br><span class="line"><span class="comment"> * acquire.  If this method reports failure, the acquire method</span></span><br><span class="line"><span class="comment"> * may queue the thread, if it is not already queued, until it is</span></span><br><span class="line"><span class="comment"> * signalled by a release from some other thread.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;The default implementation throws &#123;<span class="doctag">@link</span></span></span><br><span class="line"><span class="comment"> * UnsupportedOperationException&#125;.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> arg the acquire argument. This value is always the one</span></span><br><span class="line"><span class="comment"> *        passed to an acquire method, or is the value saved on entry</span></span><br><span class="line"><span class="comment"> *        to a condition wait.  The value is otherwise uninterpreted</span></span><br><span class="line"><span class="comment"> *        and can represent anything you like.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> a negative value on failure; zero if acquisition in shared</span></span><br><span class="line"><span class="comment"> *         mode succeeded but no subsequent shared-mode acquire can</span></span><br><span class="line"><span class="comment"> *         succeed; and a positive value if acquisition in shared</span></span><br><span class="line"><span class="comment"> *         mode succeeded and subsequent shared-mode acquires might</span></span><br><span class="line"><span class="comment"> *         also succeed, in which case a subsequent waiting thread</span></span><br><span class="line"><span class="comment"> *         must check availability. (Support for three different</span></span><br><span class="line"><span class="comment"> *         return values enables this method to be used in contexts</span></span><br><span class="line"><span class="comment"> *         where acquires only sometimes act exclusively.)  Upon</span></span><br><span class="line"><span class="comment"> *         success, this object has been acquired.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> IllegalMonitorStateException if acquiring would place this</span></span><br><span class="line"><span class="comment"> *         synchronizer in an illegal state. This exception must be</span></span><br><span class="line"><span class="comment"> *         thrown in a consistent fashion for synchronization to work</span></span><br><span class="line"><span class="comment"> *         correctly.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> UnsupportedOperationException if shared mode is not supported</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">protected</span> <span class="type">int</span> <span class="title function_">tryAcquireShared</span><span class="params">(<span class="type">int</span> arg)</span> &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">UnsupportedOperationException</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-4-6-tryReleaseShared方法"><a href="#2-4-6-tryReleaseShared方法" class="headerlink" title="2.4.6 tryReleaseShared方法"></a>2.4.6 tryReleaseShared方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/** </span></span><br><span class="line"><span class="comment"> * 共享模式下的释放锁</span></span><br><span class="line"><span class="comment"> * Attempts to set the state to reflect a release in shared mode.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;This method is always invoked by the thread performing release.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;The default implementation throws</span></span><br><span class="line"><span class="comment"> * &#123;<span class="doctag">@link</span> UnsupportedOperationException&#125;.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> arg the release argument. This value is always the one</span></span><br><span class="line"><span class="comment"> *        passed to a release method, or the current state value upon</span></span><br><span class="line"><span class="comment"> *        entry to a condition wait.  The value is otherwise</span></span><br><span class="line"><span class="comment"> *        uninterpreted and can represent anything you like.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> &#123;<span class="doctag">@code</span> true&#125; if this release of shared mode may permit a</span></span><br><span class="line"><span class="comment"> *         waiting acquire (shared or exclusive) to succeed; and</span></span><br><span class="line"><span class="comment"> *         &#123;<span class="doctag">@code</span> false&#125; otherwise</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> IllegalMonitorStateException if releasing would place this</span></span><br><span class="line"><span class="comment"> *         synchronizer in an illegal state. This exception must be</span></span><br><span class="line"><span class="comment"> *         thrown in a consistent fashion for synchronization to work</span></span><br><span class="line"><span class="comment"> *         correctly.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> UnsupportedOperationException if shared mode is not supported</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">protected</span> <span class="type">boolean</span> <span class="title function_">tryReleaseShared</span><span class="params">(<span class="type">int</span> arg)</span> &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">UnsupportedOperationException</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-4-7-isHeldExclusively方法"><a href="#2-4-7-isHeldExclusively方法" class="headerlink" title="2.4.7 isHeldExclusively方法"></a>2.4.7 isHeldExclusively方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 返回是否以独占模式获有锁</span></span><br><span class="line"><span class="comment"> * Returns &#123;<span class="doctag">@code</span> true&#125; if synchronization is held exclusively with</span></span><br><span class="line"><span class="comment"> * respect to the current (calling) thread.  This method is invoked</span></span><br><span class="line"><span class="comment"> * upon each call to a non-waiting &#123;<span class="doctag">@link</span> ConditionObject&#125; method.</span></span><br><span class="line"><span class="comment"> * (Waiting methods instead invoke &#123;<span class="doctag">@link</span> #release&#125;.)</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;The default implementation throws &#123;<span class="doctag">@link</span></span></span><br><span class="line"><span class="comment"> * UnsupportedOperationException&#125;. This method is invoked</span></span><br><span class="line"><span class="comment"> * internally only within &#123;<span class="doctag">@link</span> ConditionObject&#125; methods, so need</span></span><br><span class="line"><span class="comment"> * not be defined if conditions are not used.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> &#123;<span class="doctag">@code</span> true&#125; if synchronization is held exclusively;</span></span><br><span class="line"><span class="comment"> *         &#123;<span class="doctag">@code</span> false&#125; otherwise 如果同步过程中保持互斥模式，返回true,反之返回false</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> UnsupportedOperationException if conditions are not supported</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">protected</span> <span class="type">boolean</span> <span class="title function_">isHeldExclusively</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">UnsupportedOperationException</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="2-4-8-addWaiter方法"><a href="#2-4-8-addWaiter方法" class="headerlink" title="2.4.8  addWaiter方法"></a>2.4.8  addWaiter方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 通过当前线程和给定的模式(独占/共享模式)来创建节点并进行节点入队 </span></span><br><span class="line"><span class="comment"> * Creates and enqueues node for current thread and given mode.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * Node.EXCLUSIVE表示独占模式，Node.SHARED表示共享模式</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> the new node 返回新的节点</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">private</span> Node <span class="title function_">addWaiter</span><span class="params">(Node mode)</span> &#123;</span><br><span class="line">    <span class="comment">// 新建与一个当前线程关联的node</span></span><br><span class="line">    <span class="type">Node</span> <span class="variable">node</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Node</span>(Thread.currentThread(), mode); </span><br><span class="line">    <span class="comment">// Try the fast path of enq; backup to full enq on failure</span></span><br><span class="line">    <span class="comment">// 首先为当前线程以指定模式构建一个Node节点，然后尝试快速入队的方式加入到同步队列中去</span></span><br><span class="line">    <span class="comment">// 获取尾结点</span></span><br><span class="line">    <span class="type">Node</span> <span class="variable">pred</span> <span class="operator">=</span> tail;</span><br><span class="line">    <span class="comment">// 如果尾结点不为空</span></span><br><span class="line">    <span class="keyword">if</span> (pred != <span class="literal">null</span>) &#123;</span><br><span class="line">        <span class="comment">// 将尾结点链接到新节点的前置节点</span></span><br><span class="line">        node.prev = pred;</span><br><span class="line">        <span class="comment">// CAS尝试将新建的node加入到队尾</span></span><br><span class="line">        <span class="keyword">if</span> (compareAndSetTail(pred, node)) &#123;</span><br><span class="line">            <span class="comment">// 如果CAS成功,将之前的尾结点的后继节点设置为新节点指针,即新节点e加入到队尾</span></span><br><span class="line">            pred.next = node;</span><br><span class="line">            <span class="comment">// 返回设置好的节点</span></span><br><span class="line">            <span class="keyword">return</span> node;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 如果没有尾结点，则初始化队列</span></span><br><span class="line">    enq(node);</span><br><span class="line">    <span class="comment">// 返回当前节点</span></span><br><span class="line">    <span class="keyword">return</span> node;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-4-9-enq方法"><a href="#2-4-9-enq方法" class="headerlink" title="2.4.9 enq方法"></a>2.4.9 enq方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 将节点插入队列，必要时进行初始化。</span></span><br><span class="line"><span class="comment"> * Inserts node into queue, initializing if necessary. See picture above.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> node the node to insert 要插入的节点</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> node&#x27;s predecessor 返回节点的前置节点</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">private</span> Node <span class="title function_">enq</span><span class="params">(<span class="keyword">final</span> Node node)</span> &#123;</span><br><span class="line">    <span class="comment">// 通过一个无条件的循环，知道将构建一个空的head，然后将当前节点加入到空的head的后面，构成一个同步队列</span></span><br><span class="line">    <span class="keyword">for</span> (;;) &#123;</span><br><span class="line">        <span class="comment">// 获取尾结点</span></span><br><span class="line">        <span class="type">Node</span> <span class="variable">t</span> <span class="operator">=</span> tail;</span><br><span class="line">        <span class="keyword">if</span> (t == <span class="literal">null</span>) &#123; <span class="comment">// Must initialize 若尾结点为null，必须初始化</span></span><br><span class="line">            <span class="comment">// CAS尝试设置新节点为head</span></span><br><span class="line">            <span class="keyword">if</span> (compareAndSetHead(<span class="keyword">new</span> <span class="title class_">Node</span>()))</span><br><span class="line">                <span class="comment">// CAS成功后，头节点就是尾结点</span></span><br><span class="line">                tail = head;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="comment">// 如果尾结点不为null,将node的前置节点设置为t(尾结点)</span></span><br><span class="line">            node.prev = t;</span><br><span class="line">            <span class="comment">// CAS将node设置为尾结点，设置成功即tail就是node</span></span><br><span class="line">            <span class="keyword">if</span> (compareAndSetTail(t, node)) &#123;</span><br><span class="line">                <span class="comment">// 设置t的下一个节点是node节点，即将node节点是尾结点</span></span><br><span class="line">                t.next = node;</span><br><span class="line">                <span class="comment">// 返回节点的前置节点</span></span><br><span class="line">                <span class="keyword">return</span> t;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="2-4-10-setHead方法"><a href="#2-4-10-setHead方法" class="headerlink" title="2.4.10 setHead方法"></a>2.4.10 setHead方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 将队列头设置为节点，从而出队。</span></span><br><span class="line"><span class="comment"> * 仅由获取方法调用。出于GC的考虑，还会清空未使用的字段，并抑制不必要的信号和遍历。</span></span><br><span class="line"><span class="comment"> * Sets head of queue to be node, thus dequeuing. Called only by</span></span><br><span class="line"><span class="comment"> * acquire methods.  Also nulls out unused fields for sake of GC</span></span><br><span class="line"><span class="comment"> * and to suppress unnecessary signals and traversals.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> node the node</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">setHead</span><span class="params">(Node node)</span> &#123;</span><br><span class="line">    <span class="comment">// 将node设置为头结点</span></span><br><span class="line">    head = node;</span><br><span class="line">    <span class="comment">// node的线程变量设置为null</span></span><br><span class="line">    node.thread = <span class="literal">null</span>;</span><br><span class="line">    <span class="comment">// node的前置节点设置为null</span></span><br><span class="line">    node.prev = <span class="literal">null</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-4-11-acquireQueued方法"><a href="#2-4-11-acquireQueued方法" class="headerlink" title="2.4.11 acquireQueued方法"></a>2.4.11 acquireQueued方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 以互斥的不间断模式获取已经在队列中的线程。用于条件等待方法以及获取。</span></span><br><span class="line"><span class="comment"> * Acquires in exclusive uninterruptible mode for thread already in</span></span><br><span class="line"><span class="comment"> * queue. Used by condition wait methods as well as acquire.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> node the node node节点</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> arg the acquire argument  获取的参数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> &#123;<span class="doctag">@code</span> true&#125; if interrupted while waiting 若在等待时中断返回true</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">final</span> <span class="type">boolean</span> <span class="title function_">acquireQueued</span><span class="params">(<span class="keyword">final</span> Node node, <span class="type">int</span> arg)</span> &#123;</span><br><span class="line">    <span class="comment">// 定义失败的标志变量,默认为true</span></span><br><span class="line">    <span class="type">boolean</span> <span class="variable">failed</span> <span class="operator">=</span> <span class="literal">true</span>;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">// 定义中断的标志变量,默认为true</span></span><br><span class="line">        <span class="type">boolean</span> <span class="variable">interrupted</span> <span class="operator">=</span> <span class="literal">false</span>;</span><br><span class="line">        <span class="comment">// 无条件循环</span></span><br><span class="line">        <span class="keyword">for</span> (;;) &#123;</span><br><span class="line">            <span class="comment">// 获取node节点的前置节点</span></span><br><span class="line">            <span class="keyword">final</span> <span class="type">Node</span> <span class="variable">p</span> <span class="operator">=</span> node.predecessor();</span><br><span class="line">            <span class="comment">// //判断前置节点是不是head节点，如果是的话，则会再次尝试去获取锁</span></span><br><span class="line">            <span class="keyword">if</span> (p == head &amp;&amp; tryAcquire(arg)) &#123;</span><br><span class="line">                <span class="comment">// 将node设置为头节点</span></span><br><span class="line">                setHead(node);</span><br><span class="line">                <span class="comment">// p的后继节点设置为null</span></span><br><span class="line">                p.next = <span class="literal">null</span>; <span class="comment">// help GC 方便GC</span></span><br><span class="line">                <span class="comment">// 设置失败标志failed为false</span></span><br><span class="line">                failed = <span class="literal">false</span>;</span><br><span class="line">                <span class="comment">// 返回中断标志interrupted为false</span></span><br><span class="line">                <span class="keyword">return</span> interrupted;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (shouldParkAfterFailedAcquire(p, node) &amp;&amp; <span class="comment">// 如果前一个节点不是head节点，则设置前一个非取消节点的状态是signal，以确保在前一个线程释放锁的时候能唤醒当前线程</span></span><br><span class="line">                parkAndCheckInterrupt())  <span class="comment">// 挂起当前线程，并且返回当前线程是否被中断过(会清空中断状态，只有在被唤醒的时候才能从park()方法返回)</span></span><br><span class="line">                interrupted = <span class="literal">true</span>;  <span class="comment">// 设置中断标志为true</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (failed)</span><br><span class="line">            <span class="comment">// 如果被中断失败过，则把该节点从同步队列中删除</span></span><br><span class="line">            cancelAcquire(node); </span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="2-4-12-selfInterrupt方法"><a href="#2-4-12-selfInterrupt方法" class="headerlink" title="2.4.12 selfInterrupt方法"></a>2.4.12 selfInterrupt方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 一种简便的方式中断当前线程</span></span><br><span class="line"><span class="comment"> * Convenience method to interrupt current thread.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">selfInterrupt</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="comment">// 这个就很简单了,直接调用当前线程的interrupt()</span></span><br><span class="line">    Thread.currentThread().interrupt();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-4-13-acquire方法"><a href="#2-4-13-acquire方法" class="headerlink" title="2.4.13 acquire方法"></a>2.4.13 acquire方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 以独占模式获取，忽略中断。</span></span><br><span class="line"><span class="comment"> * 通过至少调用一次tryAcquire的实现返回成功。</span></span><br><span class="line"><span class="comment"> * 否则，线程将排队，有可能反复阻塞和解除阻塞，调用#tryAcquire直到成功。</span></span><br><span class="line"><span class="comment"> * 此方法可以用于实现方法Lock＃lock()。</span></span><br><span class="line"><span class="comment"> * Acquires in exclusive mode, ignoring interrupts.  Implemented</span></span><br><span class="line"><span class="comment"> * by invoking at least once &#123;<span class="doctag">@link</span> #tryAcquire&#125;,</span></span><br><span class="line"><span class="comment"> * returning on success.  Otherwise the thread is queued, possibly</span></span><br><span class="line"><span class="comment"> * repeatedly blocking and unblocking, invoking &#123;<span class="doctag">@link</span></span></span><br><span class="line"><span class="comment"> * #tryAcquire&#125; until success.  This method can be used</span></span><br><span class="line"><span class="comment"> * to implement method &#123;<span class="doctag">@link</span> Lock#lock&#125;.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> arg the acquire argument.  This value is conveyed to</span></span><br><span class="line"><span class="comment"> *        &#123;<span class="doctag">@link</span> #tryAcquire&#125; but is otherwise uninterpreted and</span></span><br><span class="line"><span class="comment"> *        can represent anything you like.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title function_">acquire</span><span class="params">(<span class="type">int</span> arg)</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (!tryAcquire(arg) &amp;&amp;</span><br><span class="line">        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))</span><br><span class="line">        <span class="comment">// 如果tryAcquire获取锁失败，中断当前线程，并且创建一个代表当前线程的结点加入到等待队列的尾部</span></span><br><span class="line">        <span class="comment">// 将新加入的结点放入队列之后，这个结点有两种状态，要么获取锁，要么就挂起，如果这个结点不是头结点的后继节点，就看看这个结点是否应该挂起，如果应该挂起，就挂起当前结点，是否应该挂起是通过shouldParkAfterFailedAcquire方法来判断的 　</span></span><br><span class="line">        selfInterrupt();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="2-4-14-transferForSignal方法"><a href="#2-4-14-transferForSignal方法" class="headerlink" title="2.4.14 transferForSignal方法"></a>2.4.14 transferForSignal方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 将条件等待队列节点转移到AQS的FIFO同步队列中。</span></span><br><span class="line"><span class="comment"> * 如果成功，则返回true。否则该node在signal之前被取消。</span></span><br><span class="line"><span class="comment"> * Transfers a node from a condition queue onto sync queue.</span></span><br><span class="line"><span class="comment"> * Returns true if successful.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> node the node</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> true if successfully transferred (else the node was</span></span><br><span class="line"><span class="comment"> * cancelled before signal)</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">final</span> <span class="type">boolean</span> <span class="title function_">transferForSignal</span><span class="params">(Node node)</span> &#123;</span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * 如果CAS失败,无法更改waitStatus，则该节点在signal之前被取消了,返回false。</span></span><br><span class="line"><span class="comment">     * If cannot change waitStatus, the node has been cancelled.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">if</span> (!compareAndSetWaitStatus(node, Node.CONDITION, <span class="number">0</span>))</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * 追加到队列上，然后尝试将前一个节点的waitStatus设置为表示线程正在(可能)正在等待。</span></span><br><span class="line"><span class="comment">     * 如果取消设置或尝试设置waitStatus失败，请唤醒以重新同步（在这种情况下，waitStatus可能会短暂无害地出现错误）。</span></span><br><span class="line"><span class="comment">     * Splice onto queue and try to set waitStatus of predecessor to</span></span><br><span class="line"><span class="comment">     * indicate that thread is (probably) waiting. If cancelled or</span></span><br><span class="line"><span class="comment">     * attempt to set waitStatus fails, wake up to resync (in which</span></span><br><span class="line"><span class="comment">     * case the waitStatus can be transiently and harmlessly wrong).</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="comment">// 进行入队操作</span></span><br><span class="line">    <span class="type">Node</span> <span class="variable">p</span> <span class="operator">=</span> enq(node);</span><br><span class="line">    <span class="comment">// 获取入队节点的前继节点的状态</span></span><br><span class="line">    <span class="type">int</span> <span class="variable">ws</span> <span class="operator">=</span> p.waitStatus;</span><br><span class="line">    <span class="comment">// 若前继节点为Cancelled节点(状态为1,大于0的都是取消节点)，或非取消节点CAS设置为SIGNAL延迟唤醒，通过LockSupport.unpark唤醒线程</span></span><br><span class="line">    <span class="keyword">if</span> (ws &gt; <span class="number">0</span> || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))</span><br><span class="line">        LockSupport.unpark(node.thread);</span><br><span class="line">    <span class="comment">// 唤醒成功后返回true</span></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-4-15-fullyRelease方法"><a href="#2-4-15-fullyRelease方法" class="headerlink" title="2.4.15 fullyRelease方法"></a>2.4.15 fullyRelease方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 用当前state值调用释放；返回保存状态。 </span></span><br><span class="line"><span class="comment"> * 取消节点并在失败时引发异常。</span></span><br><span class="line"><span class="comment"> * Invokes release with current state value; returns saved state.</span></span><br><span class="line"><span class="comment"> * Cancels node and throws exception on failure.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> node the condition node for this wait 此等待的条件节点</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> previous sync state 先前的同步状态</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">final</span> <span class="type">int</span> <span class="title function_">fullyRelease</span><span class="params">(Node node)</span> &#123;</span><br><span class="line">    <span class="comment">// 定义failed,作为失败标记</span></span><br><span class="line">    <span class="type">boolean</span> <span class="variable">failed</span> <span class="operator">=</span> <span class="literal">true</span>;</span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">        <span class="comment">// 获取state状态值</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">savedState</span> <span class="operator">=</span> getState();</span><br><span class="line">        <span class="comment">// 根据状态释放</span></span><br><span class="line">        <span class="keyword">if</span> (release(savedState)) &#123;</span><br><span class="line">            <span class="comment">// 释放成功,失败变量标记为false</span></span><br><span class="line">            failed = <span class="literal">false</span>;</span><br><span class="line">            <span class="comment">// 返回先前的状态</span></span><br><span class="line">            <span class="keyword">return</span> savedState;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalMonitorStateException</span>();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (failed)</span><br><span class="line">            <span class="comment">// 如果取消节点被释放失败,则节点重新设置为等待节点</span></span><br><span class="line">            node.waitStatus = Node.CANCELLED;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-4-16-isOnSyncQueue方法"><a href="#2-4-16-isOnSyncQueue方法" class="headerlink" title="2.4.16 isOnSyncQueue方法"></a>2.4.16 isOnSyncQueue方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 判断节点是否在同步队列中。</span></span><br><span class="line"><span class="comment"> * Returns true if a node, always one that was initially placed on</span></span><br><span class="line"><span class="comment"> * a condition queue, is now waiting to reacquire on sync queue.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> node the node</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> true if is reacquiring</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">final</span> <span class="type">boolean</span> <span class="title function_">isOnSyncQueue</span><span class="params">(Node node)</span> &#123;</span><br><span class="line">    <span class="comment">// 判断节点的状态，如果状态是CONDITION，说明节点肯定不在同步队列中，同时哪怕同步队列是刚刚初始化的，也会有一个冗余的头节点存在，所以节点的前驱节点如果为null，那么节点也肯定不在同步队列中，返回fasle</span></span><br><span class="line">    <span class="keyword">if</span> (node.waitStatus == Node.CONDITION || node.prev == <span class="literal">null</span>)</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    <span class="comment">// 节点的后继节点不为null，说明节点肯定在队列中，返回true，这里很重要的一点要明白，prev和next都是针对同步队列的节点</span></span><br><span class="line">    <span class="keyword">if</span> (node.next != <span class="literal">null</span>) <span class="comment">// If has successor, it must be on queue</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * 调用findNodeFromTail，具体返回结果看findNodeFromTail()方法返回值，可以把这个方法想象成一个兜底的方法.</span></span><br><span class="line"><span class="comment">     * node.prev可以为非null，但尚未进入队列，因为将其放入队列的CAS可能会失败。因此，我们必须从尾部遍历以确保它确实做到了。</span></span><br><span class="line"><span class="comment">     * 在此方法的调用中，它将始终处于尾部，并且除非CAS失败（这不太可能），否则它将一直存在，因此我们几乎不会遍历太多。</span></span><br><span class="line"><span class="comment">     * node.prev can be non-null, but not yet on queue because</span></span><br><span class="line"><span class="comment">     * the CAS to place it on queue can fail. So we have to</span></span><br><span class="line"><span class="comment">     * traverse from tail to make sure it actually made it.  It</span></span><br><span class="line"><span class="comment">     * will always be near the tail in calls to this method, and</span></span><br><span class="line"><span class="comment">     * unless the CAS failed (which is unlikely), it will be</span></span><br><span class="line"><span class="comment">     * there, so we hardly ever traverse much.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">return</span> findNodeFromTail(node);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-4-17-findNodeFromTail方法"><a href="#2-4-17-findNodeFromTail方法" class="headerlink" title="2.4.17  findNodeFromTail方法"></a>2.4.17  findNodeFromTail方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 如果节点在同步队列中（从尾向后搜索）,则返回true。 </span></span><br><span class="line"><span class="comment"> * 仅在isOnSyncQueue需要时调用。</span></span><br><span class="line"><span class="comment"> * Returns true if node is on sync queue by searching backwards from tail.</span></span><br><span class="line"><span class="comment"> * Called only when needed by isOnSyncQueue.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> true if present</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">private</span> <span class="type">boolean</span> <span class="title function_">findNodeFromTail</span><span class="params">(Node node)</span> &#123;</span><br><span class="line">    <span class="comment">// 取尾结点</span></span><br><span class="line">    <span class="type">Node</span> <span class="variable">t</span> <span class="operator">=</span> tail;</span><br><span class="line">    <span class="keyword">for</span> (;;) &#123;</span><br><span class="line">        <span class="comment">// 如果尾结点就是当前的node,则表示node节点在同步队列中，直接返回true。</span></span><br><span class="line">        <span class="keyword">if</span> (t == node)</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        <span class="comment">// 如果尾结点为null,直接返回false</span></span><br><span class="line">        <span class="keyword">if</span> (t == <span class="literal">null</span>)</span><br><span class="line">            <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">        <span class="comment">// 将指针前移动，指向当前节点t的前一个节点</span></span><br><span class="line">        t = t.prev;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-4-18-acquireInterruptibly方法"><a href="#2-4-18-acquireInterruptibly方法" class="headerlink" title="2.4.18  acquireInterruptibly方法"></a>2.4.18  acquireInterruptibly方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 以独占模式获取锁，如果中断则中止。</span></span><br><span class="line"><span class="comment"> * 否则，线程将排队，并可能反复阻塞和解除阻塞，然后调用tryAcquire</span></span><br><span class="line"><span class="comment"> * 直到成功或线程被中断为止。该方法可以用于实现Lock＃lockInterruptible方法。</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * Acquires in exclusive mode, aborting if interrupted.</span></span><br><span class="line"><span class="comment"> * Implemented by first checking interrupt status, then invoking</span></span><br><span class="line"><span class="comment"> * at least once &#123;<span class="doctag">@link</span> #tryAcquire&#125;, returning on</span></span><br><span class="line"><span class="comment"> * success.  Otherwise the thread is queued, possibly repeatedly</span></span><br><span class="line"><span class="comment"> * blocking and unblocking, invoking &#123;<span class="doctag">@link</span> #tryAcquire&#125;</span></span><br><span class="line"><span class="comment"> * until success or the thread is interrupted.  This method can be</span></span><br><span class="line"><span class="comment"> * used to implement method &#123;<span class="doctag">@link</span> Lock#lockInterruptibly&#125;.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> arg the acquire argument.  This value is conveyed to</span></span><br><span class="line"><span class="comment"> *        &#123;<span class="doctag">@link</span> #tryAcquire&#125; but is otherwise uninterpreted and</span></span><br><span class="line"><span class="comment"> *        can represent anything you like.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> InterruptedException if the current thread is interrupted 如果当前线程被中断抛出InterruptedException</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title function_">acquireInterruptibly</span><span class="params">(<span class="type">int</span> arg)</span></span><br><span class="line">        <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">    <span class="comment">// 如果当前线程被中断抛出InterruptedException</span></span><br><span class="line">    <span class="keyword">if</span> (Thread.interrupted())</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">InterruptedException</span>();</span><br><span class="line">    <span class="comment">// 尝试获取锁</span></span><br><span class="line">    <span class="keyword">if</span> (!tryAcquire(arg))</span><br><span class="line">        <span class="comment">// 如果没有获取锁，在排他可中断模式下再次获取锁。</span></span><br><span class="line">        doAcquireInterruptibly(arg);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-4-19-release方法"><a href="#2-4-19-release方法" class="headerlink" title="2.4.19 release方法"></a>2.4.19 release方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 在独占模式下释放锁。</span></span><br><span class="line"><span class="comment"> * 如果tryRelease返回true，则通过解锁一个或多个线程来实现。</span></span><br><span class="line"><span class="comment"> * 方法可用于Lock＃unlock方法实现</span></span><br><span class="line"><span class="comment"> * Releases in exclusive mode.  Implemented by unblocking one or</span></span><br><span class="line"><span class="comment"> * more threads if &#123;<span class="doctag">@link</span> #tryRelease&#125; returns true.</span></span><br><span class="line"><span class="comment"> * This method can be used to implement method &#123;<span class="doctag">@link</span> Lock#unlock&#125;.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> arg the release argument.  This value is conveyed to</span></span><br><span class="line"><span class="comment"> *        &#123;<span class="doctag">@link</span> #tryRelease&#125; but is otherwise uninterpreted and</span></span><br><span class="line"><span class="comment"> *        can represent anything you like.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> the value returned from &#123;<span class="doctag">@link</span> #tryRelease&#125;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="type">boolean</span> <span class="title function_">release</span><span class="params">(<span class="type">int</span> arg)</span> &#123;</span><br><span class="line">    <span class="comment">// 根据参数释放锁</span></span><br><span class="line">    <span class="keyword">if</span> (tryRelease(arg)) &#123;</span><br><span class="line">        </span><br><span class="line">        <span class="comment">// 取出head节点</span></span><br><span class="line">        <span class="type">Node</span> <span class="variable">h</span> <span class="operator">=</span> head;</span><br><span class="line">        <span class="comment">// 如果head节点不为null,并且head的等待状态不是待等待状态</span></span><br><span class="line">        <span class="keyword">if</span> (h != <span class="literal">null</span> &amp;&amp; h.waitStatus != <span class="number">0</span>)</span><br><span class="line">            <span class="comment">// 如果存在后继者，唤醒节点的后继节点</span></span><br><span class="line">            unparkSuccessor(h);</span><br><span class="line">        <span class="comment">// 如果释放成功,返回true</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 释放锁失败</span></span><br><span class="line">    <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-4-20-unparkSuccessor方法"><a href="#2-4-20-unparkSuccessor方法" class="headerlink" title="2.4.20 unparkSuccessor方法"></a>2.4.20 unparkSuccessor方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 唤醒节点的后继者（如果存在）。</span></span><br><span class="line"><span class="comment"> * Wakes up node&#x27;s successor, if one exists.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> node the node</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">unparkSuccessor</span><span class="params">(Node node)</span> &#123;</span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * 如果状态为负（即可能需要signal），请尝试以清除预期的信号。如果此失败或通过等待线程更改状态，则可以。</span></span><br><span class="line"><span class="comment">     * If status is negative (i.e., possibly needing signal) try</span></span><br><span class="line"><span class="comment">     * to clear in anticipation of signalling.  It is OK if this</span></span><br><span class="line"><span class="comment">     * fails or if status is changed by waiting thread.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="type">int</span> <span class="variable">ws</span> <span class="operator">=</span> node.waitStatus;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span> (ws &lt; <span class="number">0</span>)</span><br><span class="line">        <span class="comment">// 如果小于0，即为SIGNAL、CONDITION、PROPAGATE三种之一的状态，CAS设置为等待状态为0(在队列中，等待获取锁)</span></span><br><span class="line">        compareAndSetWaitStatus(node, ws, <span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * 释放线程将保留在后续线程中，该线程通常仅是下一个节点。但是，如果取消或看似为零，则从尾部向后移动以找到实际的不可取消的后继节点。</span></span><br><span class="line"><span class="comment">     * Thread to unpark is held in successor, which is normally</span></span><br><span class="line"><span class="comment">     * just the next node.  But if cancelled or apparently null,</span></span><br><span class="line"><span class="comment">     * traverse backwards from tail to find the actual</span></span><br><span class="line"><span class="comment">     * non-cancelled successor.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="comment">// 获取node的后继节点</span></span><br><span class="line">    <span class="type">Node</span> <span class="variable">s</span> <span class="operator">=</span> node.next;</span><br><span class="line">    <span class="comment">// 如果后继节点为null，或者不为null时且后继节点的状态为取消节点时</span></span><br><span class="line">    <span class="keyword">if</span> (s == <span class="literal">null</span> || s.waitStatus &gt; <span class="number">0</span>) &#123;</span><br><span class="line">        <span class="comment">// 设置后继节点为null</span></span><br><span class="line">        s = <span class="literal">null</span>;</span><br><span class="line">        <span class="comment">// 从尾部遍历，直到前继节点为null或前继节点是node节点</span></span><br><span class="line">        <span class="keyword">for</span> (<span class="type">Node</span> <span class="variable">t</span> <span class="operator">=</span> tail; t != <span class="literal">null</span> &amp;&amp; t != node; t = t.prev)</span><br><span class="line">            <span class="comment">// 如果当前节点只要不是取消节点，则将设置s，即node的后继节点为t</span></span><br><span class="line">            <span class="keyword">if</span> (t.waitStatus &lt;= <span class="number">0</span>)</span><br><span class="line">                s = t;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 如果s不等于null，进行唤醒线程</span></span><br><span class="line">    <span class="keyword">if</span> (s != <span class="literal">null</span>)</span><br><span class="line">        LockSupport.unpark(s.thread);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-4-21-hasQueuedThreads方法"><a href="#2-4-21-hasQueuedThreads方法" class="headerlink" title="2.4.21 hasQueuedThreads方法"></a>2.4.21 hasQueuedThreads方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 查询是否有任何线程正在等待获取。请注意因为由于中断和超时引起的取消可能随时发生，所以返回值true不能保证任何其他线程都可以获取。</span></span><br><span class="line"><span class="comment"> * Queries whether any threads are waiting to acquire. Note that</span></span><br><span class="line"><span class="comment"> * because cancellations due to interrupts and timeouts may occur</span></span><br><span class="line"><span class="comment"> * at any time, a &#123;<span class="doctag">@code</span> true&#125; return does not guarantee that any</span></span><br><span class="line"><span class="comment"> * other thread will ever acquire.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;In this implementation, this operation returns in</span></span><br><span class="line"><span class="comment"> * constant time. 在此实现中，此操作按固定时间返回。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> &#123;<span class="doctag">@code</span> true&#125; if there may be other threads waiting to acquire 如果可能还有其他线程在等待获取返回true</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="type">boolean</span> <span class="title function_">hasQueuedThreads</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="comment">// 只要头结点不是尾结点，则说明队列中还有其他的线程</span></span><br><span class="line">    <span class="keyword">return</span> head != tail; </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-4-22-hasContended方法"><a href="#2-4-22-hasContended方法" class="headerlink" title="2.4.22 hasContended方法"></a>2.4.22 hasContended方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 查询是否有任何线程竞争该同步器；也就是说，如果获取方法曾经被阻止。</span></span><br><span class="line"><span class="comment"> * Queries whether any threads have ever contended to acquire this</span></span><br><span class="line"><span class="comment"> * synchronizer; that is if an acquire method has ever blocked.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;In this implementation, this operation returns in</span></span><br><span class="line"><span class="comment"> * constant time. 在此实现中，此操作按固定时间返回</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> &#123;<span class="doctag">@code</span> true&#125; if there has ever been contention</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="type">boolean</span> <span class="title function_">hasContended</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="comment">// 只要head不为null，说明有竞争</span></span><br><span class="line">    <span class="keyword">return</span> head != <span class="literal">null</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-4-23-getFirstQueuedThread方法"><a href="#2-4-23-getFirstQueuedThread方法" class="headerlink" title="2.4.23 getFirstQueuedThread方法"></a>2.4.23 getFirstQueuedThread方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 返回队列中的第一个（等待时间最长）线程，如果当前没有队列，则返回null。</span></span><br><span class="line"><span class="comment"> * Returns the first (longest-waiting) thread in the queue, or</span></span><br><span class="line"><span class="comment"> * &#123;<span class="doctag">@code</span> null&#125; if no threads are currently queued.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 在此实现中，此操作通常在固定时间内返回，但是如果其他线程正在同时修改队列，则可能会在争用中迭代。</span></span><br><span class="line"><span class="comment"> * &lt;p&gt;In this implementation, this operation normally returns in</span></span><br><span class="line"><span class="comment"> * constant time, but may iterate upon contention if other threads are</span></span><br><span class="line"><span class="comment"> * concurrently modifying the queue.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> the first (longest-waiting) thread in the queue, or</span></span><br><span class="line"><span class="comment"> *         &#123;<span class="doctag">@code</span> null&#125; if no threads are currently queued</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> Thread <span class="title function_">getFirstQueuedThread</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="comment">// handle only fast path, else relay 仅处理快速路径，否则中继</span></span><br><span class="line">    <span class="comment">// 如果头结点是尾结点说明没有等待线程，直接返回null,否则调用fullGetFirstQueuedThread()获取等待线程</span></span><br><span class="line">    <span class="keyword">return</span> (head == tail) ? <span class="literal">null</span> : fullGetFirstQueuedThread();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="2-4-24-fullGetFirstQueuedThread方法"><a href="#2-4-24-fullGetFirstQueuedThread方法" class="headerlink" title="2.4.24 fullGetFirstQueuedThread方法"></a>2.4.24 fullGetFirstQueuedThread方法</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 快速路径找不到时时调用的getFirstQueuedThread版本</span></span><br><span class="line"><span class="comment"> * Version of getFirstQueuedThread called when fastpath fails</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">private</span> Thread <span class="title function_">fullGetFirstQueuedThread</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * 第一个节点通常是head.next。尝试获取其线程字段，确保读取一致：</span></span><br><span class="line"><span class="comment">     *   如果thread字段被清空或s.prev不再是head，则一些其他线程在我们的某些读取之间同时执行setHead。 </span></span><br><span class="line"><span class="comment">     *   在遍历之前，我们尝试两次。 </span></span><br><span class="line"><span class="comment">     * The first node is normally head.next. Try to get its</span></span><br><span class="line"><span class="comment">     * thread field, ensuring consistent reads: If thread</span></span><br><span class="line"><span class="comment">     * field is nulled out or s.prev is no longer head, then</span></span><br><span class="line"><span class="comment">     * some other thread(s) concurrently performed setHead in</span></span><br><span class="line"><span class="comment">     * between some of our reads. We try this twice before</span></span><br><span class="line"><span class="comment">     * resorting to traversal.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="comment">// 定义两个节点变量，h表示头节点，s表示后继节点</span></span><br><span class="line">    Node h, s;</span><br><span class="line">    <span class="comment">// 定义一个线程变量</span></span><br><span class="line">    Thread st;</span><br><span class="line">    <span class="comment">// 条件1：如果头节点不为null，并且头节点的后继节点s不为null，并且后继节点s的前置节点是头节点head(线程不安全，需要再检测)，并且head的后继节点线程不为null</span></span><br><span class="line">    <span class="comment">// 条件2：如果头节点不为null，并且头节点的后继节点s不为null，并且后继节点s的前置节点是头节点head(线程不安全，需要再检测)，并且head的后继节点线程不为null</span></span><br><span class="line">    <span class="comment">// 条件1||条件2，若一方为true，则返回true</span></span><br><span class="line">    <span class="keyword">if</span> (((h = head) != <span class="literal">null</span> &amp;&amp; (s = h.next) != <span class="literal">null</span> &amp;&amp;</span><br><span class="line">         s.prev == head &amp;&amp; (st = s.thread) != <span class="literal">null</span>) ||</span><br><span class="line">        ((h = head) != <span class="literal">null</span> &amp;&amp; (s = h.next) != <span class="literal">null</span> &amp;&amp;</span><br><span class="line">         s.prev == head &amp;&amp; (st = s.thread) != <span class="literal">null</span>))</span><br><span class="line">        <span class="comment">// 直接返回st线程</span></span><br><span class="line">        <span class="keyword">return</span> st;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * Head的下一个字段可能尚未设置，或者在setHead之后可能未设置。</span></span><br><span class="line"><span class="comment">     * 因此，我们必须检查tail是否实际上是第一个节点。如果没有，我们继续安全地从尾节点到头节点找到保证终止。</span></span><br><span class="line"><span class="comment">     * Head&#x27;s next field might not have been set yet, or may have</span></span><br><span class="line"><span class="comment">     * been unset after setHead. So we must check to see if tail</span></span><br><span class="line"><span class="comment">     * is actually first node. If not, we continue on, safely</span></span><br><span class="line"><span class="comment">     * traversing from tail back to head to find first,</span></span><br><span class="line"><span class="comment">     * guaranteeing termination.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="comment">// 获取尾结点</span></span><br><span class="line">    <span class="type">Node</span> <span class="variable">t</span> <span class="operator">=</span> tail;</span><br><span class="line">    <span class="comment">// 定义firstThread变量，用于存在第一个线程</span></span><br><span class="line">    <span class="type">Thread</span> <span class="variable">firstThread</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">    <span class="comment">// 如果尾结点不为null,并且尾结点不是头节点，向前循环遍历</span></span><br><span class="line">    <span class="keyword">while</span> (t != <span class="literal">null</span> &amp;&amp; t != head) &#123;</span><br><span class="line">        <span class="comment">// 获取当前变量t的线程变量tt</span></span><br><span class="line">        <span class="type">Thread</span> <span class="variable">tt</span> <span class="operator">=</span> t.thread;</span><br><span class="line">        <span class="comment">// 如果线程变量不为null，则赋值于firstThread</span></span><br><span class="line">        <span class="keyword">if</span> (tt != <span class="literal">null</span>)</span><br><span class="line">            firstThread = tt;</span><br><span class="line">        <span class="comment">// 指针迁移</span></span><br><span class="line">        t = t.prev;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 返回firstThread，表示第一个等待线程</span></span><br><span class="line">    <span class="keyword">return</span> firstThread;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h1 id="3-内部类"><a href="#3-内部类" class="headerlink" title="3.内部类"></a>3.内部类</h1><h2 id="3-1-等待队列节点类"><a href="#3-1-等待队列节点类" class="headerlink" title="3.1 等待队列节点类"></a>3.1 等待队列节点类</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 等待队列节点类。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 等待队列是“CLH”(Craig，Landin和Hagersten,CLH是一种基于链表的高性能、公平的自旋锁.)锁队列的变体。</span></span><br><span class="line"><span class="comment"> * CLH锁通常用于自旋锁(spinlocks)。我们将它用于阻塞同步器，仅仅使用相同的基本策略，即在其前置节点中保存有关线程的某些控制信息。</span></span><br><span class="line"><span class="comment"> * 每个节点中的“status”字段跟踪线程是否应阻塞。节点的前置节点释放时会发出信号。否则,队列的每个节点都将用作持有单个等待线程的特定通知样式的监视器。</span></span><br><span class="line"><span class="comment"> * 虽然状态字段不控制是否授予线程锁等。线程可能会尝试获取它是否在队列中的第一位。但是先行并不能保证成功。它只赋予了竞争的权利。</span></span><br><span class="line"><span class="comment"> * 因此，当前释放的竞争线程可能需要重新等待。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 要加入CLH锁，您可以将其自动拼接成新的尾部。要出队，您只需设置head字段。</span></span><br><span class="line"><span class="comment"> *      +------+  prev +-----+       +-----+</span></span><br><span class="line"><span class="comment"> * head |      | &lt;---- |     | &lt;---- |     |  tail</span></span><br><span class="line"><span class="comment"> *      +------+       +-----+       +-----+</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 插入CLH队列只需要对“tail”执行一次原子操作，因此存在一个简单的原子分界，即从未排队到排队。</span></span><br><span class="line"><span class="comment"> * 同样，使出队仅涉及更新“head”。但是,节点需要花费更多的精力来确定其后继节点，部分是由于超时和中断而可能导致的取消。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 主要需要“prev”链接(在原始CLH锁中不使用)来处理取消。</span></span><br><span class="line"><span class="comment"> * 如果取消某个节点，则其后继节点(通常)会重新链接到一个未取消的前驱节点。</span></span><br><span class="line"><span class="comment"> * 有关自旋锁情况下类似机制的说明，请参见Scott和Scherer的论文，</span></span><br><span class="line"><span class="comment"> * 网址为: http://www.cs.rochester.edu/u/scott/synchronization/</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 我们还使用“next”链接来实现阻止机制。</span></span><br><span class="line"><span class="comment"> * 每个节点的线程ID保留在其自己的节点中，因此前驱节点通过遍历下一个链接以确定它是哪个线程，</span></span><br><span class="line"><span class="comment"> * 从而通知下一个节点唤醒。确定后继节点必须避免与新排队的节点竞争以设置其前任的“next”字段。</span></span><br><span class="line"><span class="comment"> * 如果有必要，可以通过在后继节点看起来为null时从原子更新的“tail”向后检查来解决此问题。</span></span><br><span class="line"><span class="comment"> * (或者换句话说，下一个链接是一种优化，因此我们通常不需要向后扫描。)</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 取消将一些保守性引入到基本算法中。</span></span><br><span class="line"><span class="comment"> * 由于我们必须轮询其他个节点的取消，</span></span><br><span class="line"><span class="comment"> * 因此我们可能会遗漏一个被取消的节点位于我们前面还是后面。</span></span><br><span class="line"><span class="comment"> * 要解决此问题，必须始终取消后继者，让他们稳定一个新的前驱节点，除非我们能确定一个未取消的前驱节点将承担这一责任。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * CLH队列需要一个虚拟标头节点才能开始。</span></span><br><span class="line"><span class="comment"> * 但是我们不会在构建过程中创建它们，因为如果用不竞争，那将会浪费功夫。</span></span><br><span class="line"><span class="comment"> * 取而代之的是，构造节点，并在第一次竞争时设置头和尾指针。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 等待条件的线程使用相同的节点，但是使用附加链接。条件仅需要在简单(非并行)链接队列中链接节点，因为仅当它们被互斥时才可以访问它们。</span></span><br><span class="line"><span class="comment"> * 等待时，将节点插入条件队列。收到信号后，将节点转移到主队列。 status字段的特殊值用于标记节点所在的队列。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * 感谢Dave Dice、Mark Moir、Victor Luchangco、Bill、Scherer和Michael Scott，</span></span><br><span class="line"><span class="comment"> * 以及JSR-166专家组的成员，对本课程的设计提供了有益的想法、讨论和批评。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">class</span> <span class="title class_">Node</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** 指示节点正在共享模式下等待的标记 */</span></span><br><span class="line">    <span class="comment">/** Marker to indicate a node is waiting in shared mode */</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Node</span> <span class="variable">SHARED</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Node</span>();</span><br><span class="line">    <span class="comment">/** 指示节点正在以互斥模式等待的标记 */</span></span><br><span class="line">    <span class="comment">/** Marker to indicate a node is waiting in exclusive mode */</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">Node</span> <span class="variable">EXCLUSIVE</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/** waitStatus值为1,表示线程已取消 */</span></span><br><span class="line">    <span class="comment">/** waitStatus value to indicate thread has cancelled */</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">CANCELLED</span> <span class="operator">=</span>  <span class="number">1</span>;</span><br><span class="line">    <span class="comment">/** waitStatus值为-1,表示后继节点持有的线程需要释放 */</span></span><br><span class="line">    <span class="comment">/** waitStatus value to indicate successor&#x27;s thread needs unparking */</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">SIGNAL</span>    <span class="operator">=</span> -<span class="number">1</span>;</span><br><span class="line">    <span class="comment">/** waitStatus值为-2,表示线程正在条件等待 */</span></span><br><span class="line">    <span class="comment">/** waitStatus value to indicate thread is waiting on condition */</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">CONDITION</span> <span class="operator">=</span> -<span class="number">2</span>;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * waitStatus值为-3,表示下一个acquireShared(共享模式获取锁)应该无条件传播</span></span><br><span class="line"><span class="comment">     * waitStatus value to indicate the next acquireShared should</span></span><br><span class="line"><span class="comment">     * unconditionally propagate</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">PROPAGATE</span> <span class="operator">=</span> -<span class="number">3</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 状态字段，仅采用以下值：</span></span><br><span class="line"><span class="comment">     * Status field, taking on only the values:</span></span><br><span class="line"><span class="comment">     *   SIGNAL:     The successor of this node is (or will soon be)</span></span><br><span class="line"><span class="comment">     *               blocked (via park), so the current node must</span></span><br><span class="line"><span class="comment">     *               unpark its successor when it releases or</span></span><br><span class="line"><span class="comment">     *               cancels. To avoid races, acquire methods must</span></span><br><span class="line"><span class="comment">     *               first indicate they need a signal,</span></span><br><span class="line"><span class="comment">     *               then retry the atomic acquire, and then,</span></span><br><span class="line"><span class="comment">     *               on failure, block.</span></span><br><span class="line"><span class="comment">     *   该节点的后继节点被(或将很快)被阻止(通过停放)，因此当前节点在释放或取消时必须取消停放其后继节点。</span></span><br><span class="line"><span class="comment">     *   为了避免种族冲突,acquire方法必须首先表明它们需要一个信号，然后重试原子获取，然后失败时阻塞。</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     *   CANCELLED:  This node is cancelled due to timeout or interrupt.</span></span><br><span class="line"><span class="comment">     *               Nodes never leave this state. In particular,</span></span><br><span class="line"><span class="comment">     *               a thread with cancelled node never again blocks.</span></span><br><span class="line"><span class="comment">     *   由于超时或中断,该节点被取消。节点永远不会离开此状态。特别是具有取消节点的线程永远不会再次阻塞。</span></span><br><span class="line"><span class="comment">     *   </span></span><br><span class="line"><span class="comment">     *   CONDITION:  This node is currently on a condition queue.</span></span><br><span class="line"><span class="comment">     *               It will not be used as a sync queue node</span></span><br><span class="line"><span class="comment">     *               until transferred, at which time the status</span></span><br><span class="line"><span class="comment">     *               will be set to 0. (Use of this value here has</span></span><br><span class="line"><span class="comment">     *               nothing to do with the other uses of the</span></span><br><span class="line"><span class="comment">     *               field, but simplifies mechanics.)</span></span><br><span class="line"><span class="comment">     *   该节点当前在条件队列中。在传输之前,它不会用作同步队列节点,此时状态将设置为0。(此处使用此值与字段的其他用途无关,但简化了机制)。</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     *   PROPAGATE:  A releaseShared should be propagated to other</span></span><br><span class="line"><span class="comment">     *               nodes. This is set (for head node only) in</span></span><br><span class="line"><span class="comment">     *               doReleaseShared to ensure propagation</span></span><br><span class="line"><span class="comment">     *               continues, even if other operations have</span></span><br><span class="line"><span class="comment">     *               since intervened.</span></span><br><span class="line"><span class="comment">     *   releaseShared应该传播到其他节点。在doReleaseShared中设置(此设置仅适用于头节点),以确保传播继续进行,即使由于干预而进行了其他操作。</span></span><br><span class="line"><span class="comment">     * </span></span><br><span class="line"><span class="comment">     *   0:          None of the above 以上都不是</span></span><br><span class="line"><span class="comment">     * </span></span><br><span class="line"><span class="comment">     * values按数字排列以简化使用。非负值表示节点不需要发送信号。</span></span><br><span class="line"><span class="comment">     * 因此,大多数代码不需要检查特定的值，仅需检查符号即可。</span></span><br><span class="line"><span class="comment">     * The values are arranged numerically to simplify use.</span></span><br><span class="line"><span class="comment">     * Non-negative values mean that a node doesn&#x27;t need to</span></span><br><span class="line"><span class="comment">     * signal. So, most code doesn&#x27;t need to check for particular</span></span><br><span class="line"><span class="comment">     * values, just for sign.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * 对于普通同步节点,该字段初始化为0；</span></span><br><span class="line"><span class="comment">     * 对于条件节点,该字段初始化为CONDITION。使用CAS(或在可能时使用无条件的易失性写操作)对其进行修改。</span></span><br><span class="line"><span class="comment">     * The field is initialized to 0 for normal sync nodes, and</span></span><br><span class="line"><span class="comment">     * CONDITION for condition nodes.  It is modified using CAS</span></span><br><span class="line"><span class="comment">     * (or when possible, unconditional volatile writes).</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">volatile</span> <span class="type">int</span> waitStatus;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 链接到当前节点/线程所依赖的前驱节点以检查waitStatus。</span></span><br><span class="line"><span class="comment">     * 在入队期间分配,并且仅在出队时将清空(出于GC的考虑)。</span></span><br><span class="line"><span class="comment">     * 同样，在取消前驱节点后，我们在短路的同时找到了一个永远不会存在的不可取消的前驱节点，</span></span><br><span class="line"><span class="comment">     * 因为头节点从未被取消：一个节点仅由于成功获取而成为头。 </span></span><br><span class="line"><span class="comment">     * 被取消的线程永远不会成功获取，并且只有一个线程会取消自身，而不会取消任何其他节点。</span></span><br><span class="line"><span class="comment">     * Link to predecessor node that current node/thread relies on</span></span><br><span class="line"><span class="comment">     * for checking waitStatus. Assigned during enqueuing, and nulled</span></span><br><span class="line"><span class="comment">     * out (for sake of GC) only upon dequeuing.  Also, upon</span></span><br><span class="line"><span class="comment">     * cancellation of a predecessor, we short-circuit while</span></span><br><span class="line"><span class="comment">     * finding a non-cancelled one, which will always exist</span></span><br><span class="line"><span class="comment">     * because the head node is never cancelled: A node becomes</span></span><br><span class="line"><span class="comment">     * head only as a result of successful acquire. A</span></span><br><span class="line"><span class="comment">     * cancelled thread never succeeds in acquiring, and a thread only</span></span><br><span class="line"><span class="comment">     * cancels itself, not any other node.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">volatile</span> Node prev;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 链接到当前节点/线程在释放时取消驻留的后继节点。</span></span><br><span class="line"><span class="comment">     * 在排队期间分配，在绕过已取消的前任时进行调整，并在出队时清零(出于GC的原因)。</span></span><br><span class="line"><span class="comment">     * enq操作直到附加之后才分配前驱节点的下一个字段，因此看到下一个空字段并不一定意味着节点在队列末尾。</span></span><br><span class="line"><span class="comment">     * 但是，如果下一个字段为null，则我们可以从尾部扫描上一个进行双重检查。</span></span><br><span class="line"><span class="comment">     * 被取消节点的下一个字段设置为*指向节点本身而不是null，以使isOnSyncQueue的工作更轻松。</span></span><br><span class="line"><span class="comment">     * Link to the successor node that the current node/thread</span></span><br><span class="line"><span class="comment">     * unparks upon release. Assigned during enqueuing, adjusted</span></span><br><span class="line"><span class="comment">     * when bypassing cancelled predecessors, and nulled out (for</span></span><br><span class="line"><span class="comment">     * sake of GC) when dequeued.  The enq operation does not</span></span><br><span class="line"><span class="comment">     * assign next field of a predecessor until after attachment,</span></span><br><span class="line"><span class="comment">     * so seeing a null next field does not necessarily mean that</span></span><br><span class="line"><span class="comment">     * node is at end of queue. However, if a next field appears</span></span><br><span class="line"><span class="comment">     * to be null, we can scan prev&#x27;s from the tail to</span></span><br><span class="line"><span class="comment">     * double-check.  The next field of cancelled nodes is set to</span></span><br><span class="line"><span class="comment">     * point to the node itself instead of null, to make life</span></span><br><span class="line"><span class="comment">     * easier for isOnSyncQueue.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">volatile</span> Node next;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 使该节点排队的线程。在结构上初始化,使用后消失。</span></span><br><span class="line"><span class="comment">     * The thread that enqueued this node.  Initialized on</span></span><br><span class="line"><span class="comment">     * construction and nulled out after use.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">volatile</span> Thread thread;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 链接到等待条件的下一个节点,或者共享特殊值。</span></span><br><span class="line"><span class="comment">     * 因为条件队列仅在处于独占模式时才被访问，所以我们只需要一个简单的链接队列即可在节点等待条件时保存节点。</span></span><br><span class="line"><span class="comment">     * 然后将它们转移到队列以重新获取。由于条件只能是互斥的，因此我们使用特殊值来表示共享模式来保存字段。</span></span><br><span class="line"><span class="comment">     * Link to next node waiting on condition, or the special</span></span><br><span class="line"><span class="comment">     * value SHARED.  Because condition queues are accessed only</span></span><br><span class="line"><span class="comment">     * when holding in exclusive mode, we just need a simple</span></span><br><span class="line"><span class="comment">     * linked queue to hold nodes while they are waiting on</span></span><br><span class="line"><span class="comment">     * conditions. They are then transferred to the queue to</span></span><br><span class="line"><span class="comment">     * re-acquire. And because conditions can only be exclusive,</span></span><br><span class="line"><span class="comment">     * we save a field by using special value to indicate shared</span></span><br><span class="line"><span class="comment">     * mode.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    Node nextWaiter;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 如果节点正在共享模式下等待，则返回true。</span></span><br><span class="line"><span class="comment">     * Returns true if node is waiting in shared mode.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">final</span> <span class="type">boolean</span> <span class="title function_">isShared</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> nextWaiter == SHARED;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 返回上一个节点，如果为null，则抛出NullPointerException。</span></span><br><span class="line"><span class="comment">     * 在前驱节点不能为null时使用。可以忽略空检查，但它可以帮助虚拟机。</span></span><br><span class="line"><span class="comment">     * Returns previous node, or throws NullPointerException if null.</span></span><br><span class="line"><span class="comment">     * Use when predecessor cannot be null.  The null check could</span></span><br><span class="line"><span class="comment">     * be elided, but is present to help the VM.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> the predecessor of this node 该节点的前驱节点</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">final</span> Node <span class="title function_">predecessor</span><span class="params">()</span> <span class="keyword">throws</span> NullPointerException &#123;</span><br><span class="line">        <span class="type">Node</span> <span class="variable">p</span> <span class="operator">=</span> prev;</span><br><span class="line">        <span class="keyword">if</span> (p == <span class="literal">null</span>)</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">NullPointerException</span>();</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">            <span class="keyword">return</span> p;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 空参构造</span></span><br><span class="line"><span class="comment">     * 用于建立初始标头或SHARED标记</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    Node() &#123;    <span class="comment">// Used to establish initial head or SHARED marker</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 多参数构造：支持node设置</span></span><br><span class="line"><span class="comment">     * 由addWaiter使用</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    Node(Thread thread, Node mode) &#123;     <span class="comment">// Used by addWaiter</span></span><br><span class="line">        <span class="built_in">this</span>.nextWaiter = mode;</span><br><span class="line">        <span class="built_in">this</span>.thread = thread;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 多参数构造：支持waitStatus设置</span></span><br><span class="line"><span class="comment">     * 由Condition使用</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    Node(Thread thread, <span class="type">int</span> waitStatus) &#123; <span class="comment">// Used by Condition</span></span><br><span class="line">        <span class="built_in">this</span>.waitStatus = waitStatus;</span><br><span class="line">        <span class="built_in">this</span>.thread = thread;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="3-2-条件对象类"><a href="#3-2-条件对象类" class="headerlink" title="3.2 条件对象类"></a>3.2 条件对象类</h2><h3 id="3-2-1-Condition顶层接口"><a href="#3-2-1-Condition顶层接口" class="headerlink" title="3.2.1 Condition顶层接口"></a>3.2.1 Condition顶层接口</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> java.util.concurrent.locks;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.TimeUnit;</span><br><span class="line"><span class="keyword">import</span> java.util.Date;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Condition实现可以提供Object监视器方法的行为和语义(Object中的wait、notify和notifyAll方法)，例如有保证的通知顺序，或者在执行通知时不需要锁定。</span></span><br><span class="line"><span class="comment"> * Condition本质上绑定一个锁, 要获得特定Condition实例，请使用其newCondition()方法。</span></span><br><span class="line"><span class="comment"> * 当等待Condition时，允许发生&quot;虚假唤醒&quot;,一般来说，作为对底层平台语义的让步。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@since</span> 1.5</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> Doug Lea</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">Condition</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 使当前线程等待，直到收到信号或线程可以interrupt()中断</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> InterruptedException if the current thread is interrupted</span></span><br><span class="line"><span class="comment">     *         (and interruption of thread suspension is supported)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">await</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 使当前线程等待，直到发出信号。不可中断</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">awaitUninterruptibly</span><span class="params">()</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * </span></span><br><span class="line"><span class="comment">     * 导致当前线程等待，直到被信号通知或中断，或者经过指定的等待时间(纳秒)。</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> nanosTimeout the maximum time to wait, in nanoseconds</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> an estimate of the &#123;<span class="doctag">@code</span> nanosTimeout&#125; value minus</span></span><br><span class="line"><span class="comment">     *         the time spent waiting upon return from this method.</span></span><br><span class="line"><span class="comment">     *         A positive value may be used as the argument to a</span></span><br><span class="line"><span class="comment">     *         subsequent call to this method to finish waiting out</span></span><br><span class="line"><span class="comment">     *         the desired time.  A value less than or equal to zero</span></span><br><span class="line"><span class="comment">     *         indicates that no time remains.</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> InterruptedException if the current thread is interrupted</span></span><br><span class="line"><span class="comment">     *         (and interruption of thread suspension is supported)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="type">long</span> <span class="title function_">awaitNanos</span><span class="params">(<span class="type">long</span> nanosTimeout)</span> <span class="keyword">throws</span> InterruptedException;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 使当前线程等待，直到被信号通知或中断，或者经过指定的等待时间。</span></span><br><span class="line"><span class="comment">     * 此方法在行为上等效于：awaitNanos(unit.toNanos(time)) &gt; 0。</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> time the maximum time to wait</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> unit the time unit of the &#123;<span class="doctag">@code</span> time&#125; argument</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> &#123;<span class="doctag">@code</span> false&#125; if the waiting time detectably elapsed</span></span><br><span class="line"><span class="comment">     *         before return from the method, else &#123;<span class="doctag">@code</span> true&#125;</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> InterruptedException if the current thread is interrupted</span></span><br><span class="line"><span class="comment">     *         (and interruption of thread suspension is supported)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="type">boolean</span> <span class="title function_">await</span><span class="params">(<span class="type">long</span> time, TimeUnit unit)</span> <span class="keyword">throws</span> InterruptedException;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 使当前线程等待，直到发出信号或被中断，或者指定超过了指定的期限后等待。</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> deadline the absolute time to wait until</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> &#123;<span class="doctag">@code</span> false&#125; if the deadline has elapsed upon return, else</span></span><br><span class="line"><span class="comment">     *         &#123;<span class="doctag">@code</span> true&#125;</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> InterruptedException if the current thread is interrupted</span></span><br><span class="line"><span class="comment">     *         (and interruption of thread suspension is supported)</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="type">boolean</span> <span class="title function_">awaitUntil</span><span class="params">(Date deadline)</span> <span class="keyword">throws</span> InterruptedException;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 唤醒一个等待线程。随机唤醒，重新获锁。</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">signal</span><span class="params">()</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 唤醒所有等待的线程。全部唤醒。</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">void</span> <span class="title function_">signalAll</span><span class="params">()</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="3-2-2-ConditionObject类"><a href="#3-2-2-ConditionObject类" class="headerlink" title="3.2.2 ConditionObject类"></a>3.2.2 ConditionObject类</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br><span class="line">289</span><br><span class="line">290</span><br><span class="line">291</span><br><span class="line">292</span><br><span class="line">293</span><br><span class="line">294</span><br><span class="line">295</span><br><span class="line">296</span><br><span class="line">297</span><br><span class="line">298</span><br><span class="line">299</span><br><span class="line">300</span><br><span class="line">301</span><br><span class="line">302</span><br><span class="line">303</span><br><span class="line">304</span><br><span class="line">305</span><br><span class="line">306</span><br><span class="line">307</span><br><span class="line">308</span><br><span class="line">309</span><br><span class="line">310</span><br><span class="line">311</span><br><span class="line">312</span><br><span class="line">313</span><br><span class="line">314</span><br><span class="line">315</span><br><span class="line">316</span><br><span class="line">317</span><br><span class="line">318</span><br><span class="line">319</span><br><span class="line">320</span><br><span class="line">321</span><br><span class="line">322</span><br><span class="line">323</span><br><span class="line">324</span><br><span class="line">325</span><br><span class="line">326</span><br><span class="line">327</span><br><span class="line">328</span><br><span class="line">329</span><br><span class="line">330</span><br><span class="line">331</span><br><span class="line">332</span><br><span class="line">333</span><br><span class="line">334</span><br><span class="line">335</span><br><span class="line">336</span><br><span class="line">337</span><br><span class="line">338</span><br><span class="line">339</span><br><span class="line">340</span><br><span class="line">341</span><br><span class="line">342</span><br><span class="line">343</span><br><span class="line">344</span><br><span class="line">345</span><br><span class="line">346</span><br><span class="line">347</span><br><span class="line">348</span><br><span class="line">349</span><br><span class="line">350</span><br><span class="line">351</span><br><span class="line">352</span><br><span class="line">353</span><br><span class="line">354</span><br><span class="line">355</span><br><span class="line">356</span><br><span class="line">357</span><br><span class="line">358</span><br><span class="line">359</span><br><span class="line">360</span><br><span class="line">361</span><br><span class="line">362</span><br><span class="line">363</span><br><span class="line">364</span><br><span class="line">365</span><br><span class="line">366</span><br><span class="line">367</span><br><span class="line">368</span><br><span class="line">369</span><br><span class="line">370</span><br><span class="line">371</span><br><span class="line">372</span><br><span class="line">373</span><br><span class="line">374</span><br><span class="line">375</span><br><span class="line">376</span><br><span class="line">377</span><br><span class="line">378</span><br><span class="line">379</span><br><span class="line">380</span><br><span class="line">381</span><br><span class="line">382</span><br><span class="line">383</span><br><span class="line">384</span><br><span class="line">385</span><br><span class="line">386</span><br><span class="line">387</span><br><span class="line">388</span><br><span class="line">389</span><br><span class="line">390</span><br><span class="line">391</span><br><span class="line">392</span><br><span class="line">393</span><br><span class="line">394</span><br><span class="line">395</span><br><span class="line">396</span><br><span class="line">397</span><br><span class="line">398</span><br><span class="line">399</span><br><span class="line">400</span><br><span class="line">401</span><br><span class="line">402</span><br><span class="line">403</span><br><span class="line">404</span><br><span class="line">405</span><br><span class="line">406</span><br><span class="line">407</span><br><span class="line">408</span><br><span class="line">409</span><br><span class="line">410</span><br><span class="line">411</span><br><span class="line">412</span><br><span class="line">413</span><br><span class="line">414</span><br><span class="line">415</span><br><span class="line">416</span><br><span class="line">417</span><br><span class="line">418</span><br><span class="line">419</span><br><span class="line">420</span><br><span class="line">421</span><br><span class="line">422</span><br><span class="line">423</span><br><span class="line">424</span><br><span class="line">425</span><br><span class="line">426</span><br><span class="line">427</span><br><span class="line">428</span><br><span class="line">429</span><br><span class="line">430</span><br><span class="line">431</span><br><span class="line">432</span><br><span class="line">433</span><br><span class="line">434</span><br><span class="line">435</span><br><span class="line">436</span><br><span class="line">437</span><br><span class="line">438</span><br><span class="line">439</span><br><span class="line">440</span><br><span class="line">441</span><br><span class="line">442</span><br><span class="line">443</span><br><span class="line">444</span><br><span class="line">445</span><br><span class="line">446</span><br><span class="line">447</span><br><span class="line">448</span><br><span class="line">449</span><br><span class="line">450</span><br><span class="line">451</span><br><span class="line">452</span><br><span class="line">453</span><br><span class="line">454</span><br><span class="line">455</span><br><span class="line">456</span><br><span class="line">457</span><br><span class="line">458</span><br><span class="line">459</span><br><span class="line">460</span><br><span class="line">461</span><br><span class="line">462</span><br><span class="line">463</span><br><span class="line">464</span><br><span class="line">465</span><br><span class="line">466</span><br><span class="line">467</span><br><span class="line">468</span><br><span class="line">469</span><br><span class="line">470</span><br><span class="line">471</span><br><span class="line">472</span><br><span class="line">473</span><br><span class="line">474</span><br><span class="line">475</span><br><span class="line">476</span><br><span class="line">477</span><br><span class="line">478</span><br><span class="line">479</span><br><span class="line">480</span><br><span class="line">481</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * AbstractQueuedSynchronizer的Condition实现,用作于Lock实现的基础。</span></span><br><span class="line"><span class="comment"> * Condition implementation for a &#123;<span class="doctag">@link</span></span></span><br><span class="line"><span class="comment"> * AbstractQueuedSynchronizer&#125; serving as the basis of a &#123;<span class="doctag">@link</span></span></span><br><span class="line"><span class="comment"> * Lock&#125; implementation.</span></span><br><span class="line"><span class="comment"> * 此类是可序列化的，但是所有字段都是瞬态的，因此反序列化条件没有等待的节点。</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">ConditionObject</span> <span class="keyword">implements</span> <span class="title class_">Condition</span>, java.io.Serializable &#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> <span class="variable">serialVersionUID</span> <span class="operator">=</span> <span class="number">1173984872572414699L</span>;</span><br><span class="line">    <span class="comment">/** First node of condition queue. 条件队列的第一个节点。 */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">transient</span> Node firstWaiter;</span><br><span class="line">    <span class="comment">/** Last node of condition queue. 条件队列的最后一个节点。*/</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">transient</span> Node lastWaiter;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 空参构造:创建一个新的ConditionObject实例。</span></span><br><span class="line"><span class="comment">     * Creates a new &#123;<span class="doctag">@code</span> ConditionObject&#125; instance.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="title function_">ConditionObject</span><span class="params">()</span> &#123; &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Internal methods 内部方法</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Adds a new waiter to wait queue. 添加新的等待者以等待队列。</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> its new wait node 它的新的等待节点</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> Node <span class="title function_">addConditionWaiter</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// 获取最后一个等待节点</span></span><br><span class="line">        <span class="type">Node</span> <span class="variable">t</span> <span class="operator">=</span> lastWaiter;</span><br><span class="line">        <span class="comment">// If lastWaiter is cancelled, clean out. 如果lastWaiter被取消，请清除。</span></span><br><span class="line">        <span class="comment">// 首先判断lastWaiter节点是否为空，或者是否是处于条件等待，如果不是的话则把它从等待队列中删除。</span></span><br><span class="line">        <span class="keyword">if</span> (t != <span class="literal">null</span> &amp;&amp; t.waitStatus != Node.CONDITION) &#123;</span><br><span class="line">            <span class="comment">// 剔除CONDITION节点进行重新链接</span></span><br><span class="line">            unlinkCancelledWaiters();</span><br><span class="line">            t = lastWaiter;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 构建当前线程的条件等待节点</span></span><br><span class="line">        <span class="type">Node</span> <span class="variable">node</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">Node</span>(Thread.currentThread(), Node.CONDITION);</span><br><span class="line">        <span class="keyword">if</span> (t == <span class="literal">null</span>) </span><br><span class="line">            <span class="comment">// 等待尾节点为null,此等待队列为null,把当前线程构建的条件节点加入到等待队列中去，初始化队列，此时首尾相等的队列</span></span><br><span class="line">            firstWaiter = node;</span><br><span class="line">        <span class="keyword">else</span></span><br><span class="line">             <span class="comment">// 等待尾节点不为null,,把当前线程构建的条件节点加入到等待队列中去</span></span><br><span class="line">            t.nextWaiter = node;</span><br><span class="line">        <span class="comment">// 设置尾结点</span></span><br><span class="line">        lastWaiter = node;</span><br><span class="line">        <span class="comment">// 当前线程的条件结点</span></span><br><span class="line">        <span class="keyword">return</span> node;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 从首节点向后遍历直到遇见一个非Cancelled或者为null的节点，</span></span><br><span class="line"><span class="comment">     * 并将其移除等待队列，并添加到AQS的FIFO同步队列尾部</span></span><br><span class="line"><span class="comment">     * Removes and transfers nodes until hit non-cancelled one or</span></span><br><span class="line"><span class="comment">     * null. Split out from signal in part to encourage compilers</span></span><br><span class="line"><span class="comment">     * to inline the case of no waiters.</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> first (non-null) the first node on condition queue 非空条件队列上的第一个节点</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">doSignal</span><span class="params">(Node first)</span> &#123;</span><br><span class="line">        <span class="keyword">do</span> &#123;</span><br><span class="line">            <span class="comment">// 若first头节点的nex等待节点为null,尾结点就是null</span></span><br><span class="line">            <span class="keyword">if</span> ( (firstWaiter = first.nextWaiter) == <span class="literal">null</span>)</span><br><span class="line">                lastWaiter = <span class="literal">null</span>;</span><br><span class="line">            <span class="comment">// 头节点设置为null</span></span><br><span class="line">            first.nextWaiter = <span class="literal">null</span>;</span><br><span class="line">        &#125; <span class="keyword">while</span> (!transferForSignal(first) &amp;&amp; <span class="comment">//从first开始遍历等待队列，把第一个非空、没取消的节点transfer到同步队列</span></span><br><span class="line">                 (first = firstWaiter) != <span class="literal">null</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 删除并转换所有节点。</span></span><br><span class="line"><span class="comment">     * Removes and transfers all nodes.</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> first (non-null) the first node on condition queue 非空条件队列上的第一个节点</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">doSignalAll</span><span class="params">(Node first)</span> &#123;</span><br><span class="line">        lastWaiter = firstWaiter = <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">do</span> &#123;</span><br><span class="line">            <span class="type">Node</span> <span class="variable">next</span> <span class="operator">=</span> first.nextWaiter;</span><br><span class="line">            first.nextWaiter = <span class="literal">null</span>;</span><br><span class="line">            transferForSignal(first);</span><br><span class="line">            first = next;</span><br><span class="line">        &#125; <span class="keyword">while</span> (first != <span class="literal">null</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 等待队列中为取消状态的等待节点进行取消链接</span></span><br><span class="line"><span class="comment">     * Unlinks cancelled waiter nodes from condition queue.</span></span><br><span class="line"><span class="comment">     * Called only while holding lock. This is called when</span></span><br><span class="line"><span class="comment">     * cancellation occurred during condition wait, and upon</span></span><br><span class="line"><span class="comment">     * insertion of a new waiter when lastWaiter is seen to have</span></span><br><span class="line"><span class="comment">     * been cancelled. This method is needed to avoid garbage</span></span><br><span class="line"><span class="comment">     * retention in the absence of signals. So even though it may</span></span><br><span class="line"><span class="comment">     * require a full traversal, it comes into play only when</span></span><br><span class="line"><span class="comment">     * timeouts or cancellations occur in the absence of</span></span><br><span class="line"><span class="comment">     * signals. It traverses all nodes rather than stopping at a</span></span><br><span class="line"><span class="comment">     * particular target to unlink all pointers to garbage nodes</span></span><br><span class="line"><span class="comment">     * without requiring many re-traversals during cancellation</span></span><br><span class="line"><span class="comment">     * storms.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">unlinkCancelledWaiters</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="type">Node</span> <span class="variable">t</span> <span class="operator">=</span> firstWaiter;</span><br><span class="line">        <span class="type">Node</span> <span class="variable">trail</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">        <span class="keyword">while</span> (t != <span class="literal">null</span>) &#123;</span><br><span class="line">            <span class="type">Node</span> <span class="variable">next</span> <span class="operator">=</span> t.nextWaiter;</span><br><span class="line">            <span class="keyword">if</span> (t.waitStatus != Node.CONDITION) &#123;</span><br><span class="line">                t.nextWaiter = <span class="literal">null</span>;</span><br><span class="line">                <span class="keyword">if</span> (trail == <span class="literal">null</span>)</span><br><span class="line">                    firstWaiter = next;</span><br><span class="line">                <span class="keyword">else</span></span><br><span class="line">                    trail.nextWaiter = next;</span><br><span class="line">                <span class="keyword">if</span> (next == <span class="literal">null</span>)</span><br><span class="line">                    lastWaiter = trail;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">else</span></span><br><span class="line">                trail = t;</span><br><span class="line">            t = next;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// public methods</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 将等待时间最长的线程(如果存在)从该条件的等待队列移至拥有锁的等待队列。</span></span><br><span class="line"><span class="comment">     * 首先会判断当前线程是不是独占的持有锁,然后唤醒等待队列中的第一个等待线程。</span></span><br><span class="line"><span class="comment">     * Moves the longest-waiting thread, if one exists, from the</span></span><br><span class="line"><span class="comment">     * wait queue for this condition to the wait queue for the</span></span><br><span class="line"><span class="comment">     * owning lock.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> IllegalMonitorStateException if &#123;<span class="doctag">@link</span> #isHeldExclusively&#125; </span></span><br><span class="line"><span class="comment">     *         returns &#123;<span class="doctag">@code</span> false&#125;</span></span><br><span class="line"><span class="comment">     * 如果调用isHeldExclusively返回false，说明不是处于独占模式则抛出 IllegalMonitorStateException</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title function_">signal</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (!isHeldExclusively())</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalMonitorStateException</span>();</span><br><span class="line">        <span class="type">Node</span> <span class="variable">first</span> <span class="operator">=</span> firstWaiter;</span><br><span class="line">        <span class="comment">// 头节点不为null,再doSignal</span></span><br><span class="line">        <span class="keyword">if</span> (first != <span class="literal">null</span>)</span><br><span class="line">            doSignal(first);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 将所有线程从这种情况下的等待队列移至拥有锁的等待队列。</span></span><br><span class="line"><span class="comment">     * Moves all threads from the wait queue for this condition to</span></span><br><span class="line"><span class="comment">     * the wait queue for the owning lock.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> IllegalMonitorStateException if &#123;<span class="doctag">@link</span> #isHeldExclusively&#125;</span></span><br><span class="line"><span class="comment">     *         returns &#123;<span class="doctag">@code</span> false&#125;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title function_">signalAll</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (!isHeldExclusively())</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalMonitorStateException</span>();</span><br><span class="line">        <span class="type">Node</span> <span class="variable">first</span> <span class="operator">=</span> firstWaiter;</span><br><span class="line">        <span class="keyword">if</span> (first != <span class="literal">null</span>)</span><br><span class="line">            doSignalAll(first);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 实现不间断的条件等待。</span></span><br><span class="line"><span class="comment">     * Implements uninterruptible condition wait.</span></span><br><span class="line"><span class="comment">     * &lt;ol&gt;</span></span><br><span class="line"><span class="comment">     * 保存lock state,并且通过getState()返回</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Save lock state returned by &#123;<span class="doctag">@link</span> #getState&#125;.</span></span><br><span class="line"><span class="comment">     * 以保存的state作为参数调用release()，如果失败则抛出IllegalMonitorStateException。</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Invoke &#123;<span class="doctag">@link</span> #release&#125; with saved state as argument,</span></span><br><span class="line"><span class="comment">     *      throwing IllegalMonitorStateException if it fails.</span></span><br><span class="line"><span class="comment">     * 一直阻塞直到被唤醒</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Block until signalled. </span></span><br><span class="line"><span class="comment">     * 通过调用acquire()以保存的state作为参数来重新获取锁。</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Reacquire by invoking specialized version of</span></span><br><span class="line"><span class="comment">     *      &#123;<span class="doctag">@link</span> #acquire&#125; with saved state as argument.</span></span><br><span class="line"><span class="comment">     * &lt;/ol&gt;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title function_">awaitUninterruptibly</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="comment">// 将当前线程作为条件节点添加到等待队列中</span></span><br><span class="line">        <span class="type">Node</span> <span class="variable">node</span> <span class="operator">=</span> addConditionWaiter();</span><br><span class="line">        <span class="comment">// 以当前节点的state去释放</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">savedState</span> <span class="operator">=</span> fullyRelease(node);</span><br><span class="line">        <span class="comment">// 中断标记变量，默认为false</span></span><br><span class="line">        <span class="type">boolean</span> <span class="variable">interrupted</span> <span class="operator">=</span> <span class="literal">false</span>;</span><br><span class="line">        <span class="comment">// 如果当前节点node不在同步队列中进行循环</span></span><br><span class="line">        <span class="keyword">while</span> (!isOnSyncQueue(node)) &#123;</span><br><span class="line">            <span class="comment">// 阻塞当前线程</span></span><br><span class="line">            LockSupport.park(<span class="built_in">this</span>);</span><br><span class="line">            <span class="comment">// 获取线程中断标志位</span></span><br><span class="line">            <span class="keyword">if</span> (Thread.interrupted())</span><br><span class="line">                interrupted = <span class="literal">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 若线程在等待时候被中断或者本身为中断状态，那就当前线程自己去中断</span></span><br><span class="line">        <span class="keyword">if</span> (acquireQueued(node, savedState) || interrupted)</span><br><span class="line">            selfInterrupt();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/*</span></span><br><span class="line"><span class="comment">     * For interruptible waits, we need to track whether to throw</span></span><br><span class="line"><span class="comment">     * InterruptedException, if interrupted while blocked on</span></span><br><span class="line"><span class="comment">     * condition, versus reinterrupt current thread, if</span></span><br><span class="line"><span class="comment">     * interrupted while blocked waiting to re-acquire.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">/** Mode meaning to reinterrupt on exit from wait  意味着在退出等待时重新中断 */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">REINTERRUPT</span> <span class="operator">=</span>  <span class="number">1</span>;</span><br><span class="line">    <span class="comment">/** Mode meaning to throw InterruptedException on exit from wait 在等待退出时抛出InterruptedException */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">int</span> <span class="variable">THROW_IE</span>    <span class="operator">=</span> -<span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 检查中断，如果被中断，则返回THROW_IE。</span></span><br><span class="line"><span class="comment">     * 如果在信号通知之前被中断，则返回REINTERRUPT(如果在信号通知之后),或者如果未中断则返回0.</span></span><br><span class="line"><span class="comment">     * Checks for interrupt, returning THROW_IE if interrupted</span></span><br><span class="line"><span class="comment">     * before signalled, REINTERRUPT if after signalled, or</span></span><br><span class="line"><span class="comment">     * 0 if not interrupted.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">int</span> <span class="title function_">checkInterruptWhileWaiting</span><span class="params">(Node node)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> Thread.interrupted() ?</span><br><span class="line">            (transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :</span><br><span class="line">        <span class="number">0</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 抛出InterruptedException，重新中断当前线程，或不执行任何操作。</span></span><br><span class="line"><span class="comment">     * Throws InterruptedException, reinterrupts current thread, or</span></span><br><span class="line"><span class="comment">     * does nothing, depending on mode.</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">void</span> <span class="title function_">reportInterruptAfterWait</span><span class="params">(<span class="type">int</span> interruptMode)</span></span><br><span class="line">        <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        <span class="keyword">if</span> (interruptMode == THROW_IE)</span><br><span class="line">            <span class="comment">// 为THROW_IE Mode时,抛出InterruptedException</span></span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">InterruptedException</span>();</span><br><span class="line">        <span class="keyword">else</span> <span class="keyword">if</span> (interruptMode == REINTERRUPT)</span><br><span class="line">             <span class="comment">// 为REINTERRUPT时,线程自身中断</span></span><br><span class="line">            selfInterrupt();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 实现可中断条件等待。</span></span><br><span class="line"><span class="comment">     * Implements interruptible condition wait.</span></span><br><span class="line"><span class="comment">     * &lt;ol&gt;</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; If current thread is interrupted, throw InterruptedException.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Save lock state returned by &#123;<span class="doctag">@link</span> #getState&#125;.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Invoke &#123;<span class="doctag">@link</span> #release&#125; with saved state as argument,</span></span><br><span class="line"><span class="comment">     *      throwing IllegalMonitorStateException if it fails.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Block until signalled or interrupted.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Reacquire by invoking specialized version of</span></span><br><span class="line"><span class="comment">     *      &#123;<span class="doctag">@link</span> #acquire&#125; with saved state as argument.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; If interrupted while blocked in step 4, throw InterruptedException.</span></span><br><span class="line"><span class="comment">     * &lt;/ol&gt;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title function_">await</span><span class="params">()</span> <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        <span class="comment">// 如果当前线程被中断，则抛出InterruptedException</span></span><br><span class="line">        <span class="keyword">if</span> (Thread.interrupted())</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">InterruptedException</span>();</span><br><span class="line">        <span class="comment">// 将当前线程作为条件等待节点并添加到等待队列中</span></span><br><span class="line">        <span class="type">Node</span> <span class="variable">node</span> <span class="operator">=</span> addConditionWaiter();</span><br><span class="line">        <span class="comment">// 释放锁，并返回state状态</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">savedState</span> <span class="operator">=</span> fullyRelease(node);</span><br><span class="line">        <span class="comment">// 未中断标志位</span></span><br><span class="line">        <span class="type">int</span> <span class="variable">interruptMode</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">        <span class="comment">// 若当前节点不在AQS同步队列中，循环</span></span><br><span class="line">        <span class="keyword">while</span> (!isOnSyncQueue(node)) &#123;</span><br><span class="line">            <span class="comment">// 阻塞当前节点</span></span><br><span class="line">            LockSupport.park(<span class="built_in">this</span>);</span><br><span class="line">            <span class="comment">// 检查是否中断过,如果中断过，结束循环</span></span><br><span class="line">            <span class="keyword">if</span> ((interruptMode = checkInterruptWhileWaiting(node)) != <span class="number">0</span>)</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 若线程在等待时候被中断并且中断模式不是THROW_IE不可中断模式,设置中断模式为REINTERRUPT可重新中断</span></span><br><span class="line">        <span class="keyword">if</span> (acquireQueued(node, savedState) &amp;&amp; interruptMode != THROW_IE)</span><br><span class="line">            interruptMode = REINTERRUPT;</span><br><span class="line">        <span class="keyword">if</span> (node.nextWaiter != <span class="literal">null</span>) <span class="comment">// clean up if cancelled 若node的下一个等待节点不为null,解除取消节点的链接</span></span><br><span class="line">            unlinkCancelledWaiters();</span><br><span class="line">        <span class="keyword">if</span> (interruptMode != <span class="number">0</span>) <span class="comment">// 如果有过中断,重新中断</span></span><br><span class="line">            reportInterruptAfterWait(interruptMode);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 执行定时条件等待。</span></span><br><span class="line"><span class="comment">     * Implements timed condition wait.</span></span><br><span class="line"><span class="comment">     * &lt;ol&gt;</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; If current thread is interrupted, throw InterruptedException.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Save lock state returned by &#123;<span class="doctag">@link</span> #getState&#125;.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Invoke &#123;<span class="doctag">@link</span> #release&#125; with saved state as argument,</span></span><br><span class="line"><span class="comment">     *      throwing IllegalMonitorStateException if it fails.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Block until signalled, interrupted, or timed out.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Reacquire by invoking specialized version of</span></span><br><span class="line"><span class="comment">     *      &#123;<span class="doctag">@link</span> #acquire&#125; with saved state as argument.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; If interrupted while blocked in step 4, throw InterruptedException.</span></span><br><span class="line"><span class="comment">     * &lt;/ol&gt;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">final</span> <span class="type">long</span> <span class="title function_">awaitNanos</span><span class="params">(<span class="type">long</span> nanosTimeout)</span></span><br><span class="line">        <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        <span class="keyword">if</span> (Thread.interrupted())</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">InterruptedException</span>();</span><br><span class="line">        <span class="type">Node</span> <span class="variable">node</span> <span class="operator">=</span> addConditionWaiter();</span><br><span class="line">        <span class="type">int</span> <span class="variable">savedState</span> <span class="operator">=</span> fullyRelease(node);</span><br><span class="line">        <span class="keyword">final</span> <span class="type">long</span> <span class="variable">deadline</span> <span class="operator">=</span> System.nanoTime() + nanosTimeout;</span><br><span class="line">        <span class="type">int</span> <span class="variable">interruptMode</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">while</span> (!isOnSyncQueue(node)) &#123;</span><br><span class="line">            <span class="keyword">if</span> (nanosTimeout &lt;= <span class="number">0L</span>) &#123;</span><br><span class="line">                transferAfterCancelledWait(node);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (nanosTimeout &gt;= spinForTimeoutThreshold)</span><br><span class="line">                LockSupport.parkNanos(<span class="built_in">this</span>, nanosTimeout);</span><br><span class="line">            <span class="keyword">if</span> ((interruptMode = checkInterruptWhileWaiting(node)) != <span class="number">0</span>)</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            nanosTimeout = deadline - System.nanoTime();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (acquireQueued(node, savedState) &amp;&amp; interruptMode != THROW_IE)</span><br><span class="line">            interruptMode = REINTERRUPT;</span><br><span class="line">        <span class="keyword">if</span> (node.nextWaiter != <span class="literal">null</span>)</span><br><span class="line">            unlinkCancelledWaiters();</span><br><span class="line">        <span class="keyword">if</span> (interruptMode != <span class="number">0</span>)</span><br><span class="line">            reportInterruptAfterWait(interruptMode);</span><br><span class="line">        <span class="keyword">return</span> deadline - System.nanoTime();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 实现绝对定时条件等待。</span></span><br><span class="line"><span class="comment">     * Implements absolute timed condition wait.</span></span><br><span class="line"><span class="comment">     * &lt;ol&gt;</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; If current thread is interrupted, throw InterruptedException.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Save lock state returned by &#123;<span class="doctag">@link</span> #getState&#125;.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Invoke &#123;<span class="doctag">@link</span> #release&#125; with saved state as argument,</span></span><br><span class="line"><span class="comment">     *      throwing IllegalMonitorStateException if it fails.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Block until signalled, interrupted, or timed out.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Reacquire by invoking specialized version of</span></span><br><span class="line"><span class="comment">     *      &#123;<span class="doctag">@link</span> #acquire&#125; with saved state as argument.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; If interrupted while blocked in step 4, throw InterruptedException.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; If timed out while blocked in step 4, return false, else true.</span></span><br><span class="line"><span class="comment">     * &lt;/ol&gt;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">final</span> <span class="type">boolean</span> <span class="title function_">awaitUntil</span><span class="params">(Date deadline)</span></span><br><span class="line">        <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        <span class="type">long</span> <span class="variable">abstime</span> <span class="operator">=</span> deadline.getTime();</span><br><span class="line">        <span class="keyword">if</span> (Thread.interrupted())</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">InterruptedException</span>();</span><br><span class="line">        <span class="type">Node</span> <span class="variable">node</span> <span class="operator">=</span> addConditionWaiter();</span><br><span class="line">        <span class="type">int</span> <span class="variable">savedState</span> <span class="operator">=</span> fullyRelease(node);</span><br><span class="line">        <span class="type">boolean</span> <span class="variable">timedout</span> <span class="operator">=</span> <span class="literal">false</span>;</span><br><span class="line">        <span class="type">int</span> <span class="variable">interruptMode</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">while</span> (!isOnSyncQueue(node)) &#123;</span><br><span class="line">            <span class="keyword">if</span> (System.currentTimeMillis() &gt; abstime) &#123;</span><br><span class="line">                timedout = transferAfterCancelledWait(node);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            LockSupport.parkUntil(<span class="built_in">this</span>, abstime);</span><br><span class="line">            <span class="keyword">if</span> ((interruptMode = checkInterruptWhileWaiting(node)) != <span class="number">0</span>)</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (acquireQueued(node, savedState) &amp;&amp; interruptMode != THROW_IE)</span><br><span class="line">            interruptMode = REINTERRUPT;</span><br><span class="line">        <span class="keyword">if</span> (node.nextWaiter != <span class="literal">null</span>)</span><br><span class="line">            unlinkCancelledWaiters();</span><br><span class="line">        <span class="keyword">if</span> (interruptMode != <span class="number">0</span>)</span><br><span class="line">            reportInterruptAfterWait(interruptMode);</span><br><span class="line">        <span class="keyword">return</span> !timedout;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 实现定时条件等待。可指定时间单位</span></span><br><span class="line"><span class="comment">     * Implements timed condition wait.</span></span><br><span class="line"><span class="comment">     * &lt;ol&gt;</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; If current thread is interrupted, throw InterruptedException.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Save lock state returned by &#123;<span class="doctag">@link</span> #getState&#125;.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Invoke &#123;<span class="doctag">@link</span> #release&#125; with saved state as argument,</span></span><br><span class="line"><span class="comment">     *      throwing IllegalMonitorStateException if it fails.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Block until signalled, interrupted, or timed out.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; Reacquire by invoking specialized version of</span></span><br><span class="line"><span class="comment">     *      &#123;<span class="doctag">@link</span> #acquire&#125; with saved state as argument.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; If interrupted while blocked in step 4, throw InterruptedException.</span></span><br><span class="line"><span class="comment">     * &lt;li&gt; If timed out while blocked in step 4, return false, else true.</span></span><br><span class="line"><span class="comment">     * &lt;/ol&gt;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">final</span> <span class="type">boolean</span> <span class="title function_">await</span><span class="params">(<span class="type">long</span> time, TimeUnit unit)</span></span><br><span class="line">        <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">        <span class="type">long</span> <span class="variable">nanosTimeout</span> <span class="operator">=</span> unit.toNanos(time);</span><br><span class="line">        <span class="keyword">if</span> (Thread.interrupted())</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">InterruptedException</span>();</span><br><span class="line">        <span class="type">Node</span> <span class="variable">node</span> <span class="operator">=</span> addConditionWaiter();</span><br><span class="line">        <span class="type">int</span> <span class="variable">savedState</span> <span class="operator">=</span> fullyRelease(node);</span><br><span class="line">        <span class="keyword">final</span> <span class="type">long</span> <span class="variable">deadline</span> <span class="operator">=</span> System.nanoTime() + nanosTimeout;</span><br><span class="line">        <span class="type">boolean</span> <span class="variable">timedout</span> <span class="operator">=</span> <span class="literal">false</span>;</span><br><span class="line">        <span class="type">int</span> <span class="variable">interruptMode</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">while</span> (!isOnSyncQueue(node)) &#123;</span><br><span class="line">            <span class="keyword">if</span> (nanosTimeout &lt;= <span class="number">0L</span>) &#123;</span><br><span class="line">                timedout = transferAfterCancelledWait(node);</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (nanosTimeout &gt;= spinForTimeoutThreshold)</span><br><span class="line">                LockSupport.parkNanos(<span class="built_in">this</span>, nanosTimeout);</span><br><span class="line">            <span class="keyword">if</span> ((interruptMode = checkInterruptWhileWaiting(node)) != <span class="number">0</span>)</span><br><span class="line">                <span class="keyword">break</span>;</span><br><span class="line">            nanosTimeout = deadline - System.nanoTime();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">if</span> (acquireQueued(node, savedState) &amp;&amp; interruptMode != THROW_IE)</span><br><span class="line">            interruptMode = REINTERRUPT;</span><br><span class="line">        <span class="keyword">if</span> (node.nextWaiter != <span class="literal">null</span>)</span><br><span class="line">            unlinkCancelledWaiters();</span><br><span class="line">        <span class="keyword">if</span> (interruptMode != <span class="number">0</span>)</span><br><span class="line">            reportInterruptAfterWait(interruptMode);</span><br><span class="line">        <span class="keyword">return</span> !timedout;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//  support for instrumentation</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 如果此条件是由给定的同步对象创建的，则返回true。</span></span><br><span class="line"><span class="comment">     * Returns true if this condition was created by the given</span></span><br><span class="line"><span class="comment">     * synchronization object.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> &#123;<span class="doctag">@code</span> true&#125; if owned</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">final</span> <span class="type">boolean</span> <span class="title function_">isOwnedBy</span><span class="params">(AbstractQueuedSynchronizer sync)</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> sync == AbstractQueuedSynchronizer.<span class="built_in">this</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 查询在这个等待条件对象上是否含有等待的线程。</span></span><br><span class="line"><span class="comment">     * Queries whether any threads are waiting on this condition.</span></span><br><span class="line"><span class="comment">     * Implements &#123;<span class="doctag">@link</span> AbstractQueuedSynchronizer#hasWaiters(ConditionObject)&#125;.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> &#123;<span class="doctag">@code</span> true&#125; if there are any waiting threads</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> IllegalMonitorStateException if &#123;<span class="doctag">@link</span> #isHeldExclusively&#125;</span></span><br><span class="line"><span class="comment">     *         returns &#123;<span class="doctag">@code</span> false&#125;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">final</span> <span class="type">boolean</span> <span class="title function_">hasWaiters</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (!isHeldExclusively())</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalMonitorStateException</span>();</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">Node</span> <span class="variable">w</span> <span class="operator">=</span> firstWaiter; w != <span class="literal">null</span>; w = w.nextWaiter) &#123;</span><br><span class="line">            <span class="keyword">if</span> (w.waitStatus == Node.CONDITION)</span><br><span class="line">                <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 获取等待队列的大概长度(因为查询时没有加锁，并不能保证在查找时有没有其他新节点加入到队列)</span></span><br><span class="line"><span class="comment">     * Returns an estimate of the number of threads waiting on</span></span><br><span class="line"><span class="comment">     * this condition.</span></span><br><span class="line"><span class="comment">     * Implements &#123;<span class="doctag">@link</span> AbstractQueuedSynchronizer#getWaitQueueLength(ConditionObject)&#125;.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> the estimated number of waiting threads</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> IllegalMonitorStateException if &#123;<span class="doctag">@link</span> #isHeldExclusively&#125;</span></span><br><span class="line"><span class="comment">     *         returns &#123;<span class="doctag">@code</span> false&#125;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">final</span> <span class="type">int</span> <span class="title function_">getWaitQueueLength</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (!isHeldExclusively())</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalMonitorStateException</span>();</span><br><span class="line">        <span class="type">int</span> <span class="variable">n</span> <span class="operator">=</span> <span class="number">0</span>;</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">Node</span> <span class="variable">w</span> <span class="operator">=</span> firstWaiter; w != <span class="literal">null</span>; w = w.nextWaiter) &#123;</span><br><span class="line">            <span class="keyword">if</span> (w.waitStatus == Node.CONDITION)</span><br><span class="line">                ++n;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> n;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 返回一个包含可能正在等待此条件的线程的集合。</span></span><br><span class="line"><span class="comment">     * Returns a collection containing those threads that may be</span></span><br><span class="line"><span class="comment">     * waiting on this Condition.</span></span><br><span class="line"><span class="comment">     * Implements &#123;<span class="doctag">@link</span> AbstractQueuedSynchronizer#getWaitingThreads(ConditionObject)&#125;.</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> the collection of threads</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@throws</span> IllegalMonitorStateException if &#123;<span class="doctag">@link</span> #isHeldExclusively&#125;</span></span><br><span class="line"><span class="comment">     *         returns &#123;<span class="doctag">@code</span> false&#125;</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">protected</span> <span class="keyword">final</span> Collection&lt;Thread&gt; <span class="title function_">getWaitingThreads</span><span class="params">()</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (!isHeldExclusively())</span><br><span class="line">            <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">IllegalMonitorStateException</span>();</span><br><span class="line">        ArrayList&lt;Thread&gt; list = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;Thread&gt;();</span><br><span class="line">        <span class="keyword">for</span> (<span class="type">Node</span> <span class="variable">w</span> <span class="operator">=</span> firstWaiter; w != <span class="literal">null</span>; w = w.nextWaiter) &#123;</span><br><span class="line">            <span class="keyword">if</span> (w.waitStatus == Node.CONDITION) &#123;</span><br><span class="line">                <span class="type">Thread</span> <span class="variable">t</span> <span class="operator">=</span> w.thread;</span><br><span class="line">                <span class="keyword">if</span> (t != <span class="literal">null</span>)</span><br><span class="line">                    list.add(t);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> list;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h1 id="4-AQS总结"><a href="#4-AQS总结" class="headerlink" title="4. AQS总结"></a>4. AQS总结</h1><h2 id="4-1-AQS的核心思想与实现"><a href="#4-1-AQS的核心思想与实现" class="headerlink" title="4.1 AQS的核心思想与实现"></a>4.1 AQS的核心思想与实现</h2><p>AQS的核心思想是，如果被请求的共享资源空闲，则将当前请求资源的线程设置为有效的工作线程，并将共享资源设置为锁定状态，如果被请求的共享资源被占用，那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制，这个机制AQS是用CLH队列锁实现的，即将暂时获取不到锁的线程加入到队列中。</p>
<p><strong>AQS是将每一条请求共享资源的线程封装成一个CLH锁(双向链表)队列的一个结点（Node），来实现锁的分配。</strong></p>
<p>里面维护了用volatile修饰共享变量state(0未锁定，1锁定)，线程通过CAS去改变状态，成功则获取锁成功，失败则进入等待队列，等待被唤醒。</p>
<p>AQS是自旋锁,在等待唤醒时候经常使用如下代码不停的尝试获取锁:</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">while</span> (!tryAcquire(arg)) &#123;</span><br><span class="line">    <span class="comment">// enqueue thread if it is not already queued;</span></span><br><span class="line">    <span class="comment">// possibly block current thread;</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>AQS定义了两种资源获取方式：独占（只有一个线程能访问执行，又根据是否按队列的顺序分为公平锁和非公平锁，如ReentrantLock） 和共享（多个线程可同时访问执行，如Semaphore/CountDownLatch，Semaphore、CountDownLatCh、 CyclicBarrier ）。ReentrantReadWriteLock 可以看成是组合式，允许多个线程同时对某一资源进行读。</p>
<h2 id="4-2-模板方法的抽象"><a href="#4-2-模板方法的抽象" class="headerlink" title="4.2 模板方法的抽象"></a>4.2 模板方法的抽象</h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 获取互斥锁</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title function_">acquire</span><span class="params">(<span class="type">int</span> arg)</span> &#123;</span><br><span class="line">    <span class="comment">// tryAcquire(arg)需要子类实现</span></span><br><span class="line">    <span class="keyword">if</span> (!tryAcquire(arg) &amp;&amp;</span><br><span class="line">        acquireQueued(addWaiter(Node.EXCLUSIVE), arg))</span><br><span class="line">        selfInterrupt();</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 获取互斥锁可中断</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title function_">acquireInterruptibly</span><span class="params">(<span class="type">int</span> arg)</span></span><br><span class="line">        <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">    <span class="keyword">if</span> (Thread.interrupted())</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">InterruptedException</span>();</span><br><span class="line">    <span class="comment">// tryAcquire(arg)需要子类实现</span></span><br><span class="line">    <span class="keyword">if</span> (!tryAcquire(arg))</span><br><span class="line">        doAcquireInterruptibly(arg);</span><br><span class="line">&#125;    </span><br><span class="line"><span class="comment">// 获取共享锁</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title function_">acquireShared</span><span class="params">(<span class="type">int</span> arg)</span> &#123;</span><br><span class="line">    <span class="comment">// tryAcquireShared(arg)需要子类实现</span></span><br><span class="line">    <span class="keyword">if</span> (tryAcquireShared(arg) &lt; <span class="number">0</span>)</span><br><span class="line">     doAcquireShared(arg);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 获取共享锁可中断</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">void</span> <span class="title function_">acquireSharedInterruptibly</span><span class="params">(<span class="type">int</span> arg)</span></span><br><span class="line">        <span class="keyword">throws</span> InterruptedException &#123;</span><br><span class="line">    <span class="keyword">if</span> (Thread.interrupted())</span><br><span class="line">        <span class="keyword">throw</span> <span class="keyword">new</span> <span class="title class_">InterruptedException</span>();</span><br><span class="line">    <span class="comment">// tryAcquireShared(arg)需要子类实现</span></span><br><span class="line">    <span class="keyword">if</span> (tryAcquireShared(arg) &lt; <span class="number">0</span>)</span><br><span class="line">        doAcquireSharedInterruptibly(arg);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 释放互斥锁</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="type">boolean</span> <span class="title function_">release</span><span class="params">(<span class="type">int</span> arg)</span> &#123;</span><br><span class="line">    <span class="comment">// tryRelease(arg)需要子类实现</span></span><br><span class="line">    <span class="keyword">if</span> (tryRelease(arg)) &#123;</span><br><span class="line">        <span class="type">Node</span> <span class="variable">h</span> <span class="operator">=</span> head;</span><br><span class="line">        <span class="keyword">if</span> (h != <span class="literal">null</span> &amp;&amp; h.waitStatus != <span class="number">0</span>)</span><br><span class="line">            unparkSuccessor(h);</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 释放共享锁</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">final</span> <span class="type">boolean</span> <span class="title function_">releaseShared</span><span class="params">(<span class="type">int</span> arg)</span> &#123;</span><br><span class="line">    <span class="comment">// tryReleaseShared(arg)需要子类实现</span></span><br><span class="line">    <span class="keyword">if</span> (tryReleaseShared(arg)) &#123;</span><br><span class="line">        doReleaseShared();</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>上述几个方法贯穿于ReentrantLock、ReentrantReadWriteLock、Semaphore、CountDownLatch的源码解析中，AQS为我们打开了一扇知识大门。</p>
<h1 id="5-参考资料"><a href="#5-参考资料" class="headerlink" title="5.参考资料"></a>5.参考资料</h1><ul>
<li><a target="_blank" rel="noopener" href="https://www.cnblogs.com/tong-yuan/p/AbstractQueuedSynchronizer.html">彤哥读源码</a></li>
</ul>
</section>
    <!-- Tags START -->
    
      <div class="tags">
        <span>Tags:</span>
        
  <a href="/tags#JVM及并发编程" >
    <span class="tag-code">JVM及并发编程</span>
  </a>

      </div>
    
    <!-- Tags END -->
    <!-- NAV START -->
    
  <div class="nav-container">
    <!-- reverse left and right to put prev and next in a more logic postition -->
    
      <a class="nav-left" href="/2020/06/29/%E9%9D%A2%E8%AF%95%E5%AE%98%E4%BD%A0%E7%9C%9F%E7%9A%84%E4%BA%86%E8%A7%A3Java%E5%AF%B9%E8%B1%A1%E5%90%97/">
        <span class="nav-arrow">← </span>
        
          面试官:你真的了解Java对象吗
        
      </a>
    
    
      <a class="nav-right" href="/2020/07/29/%E3%80%90MySQL%E9%AB%98%E7%BA%A7%E5%AE%9E%E6%88%98%E3%80%91-%E7%B4%A2%E5%BC%95%E4%B8%8E%E5%AD%98%E5%82%A8%E5%BC%95%E6%93%8E%E5%AD%A6%E4%B9%A0%E6%8C%87%E5%8D%97/">
        
          【MySQL高级实战】-索引与存储引擎学习指南
        
        <span class="nav-arrow"> →</span>
      </a>
    
  </div>

    <!-- NAV END -->
    <!-- 打赏 START -->
    
      <div class="money-like">
        <div class="reward-btn">
          赏
          <span class="money-code">
            <span class="alipay-code">
              <div class="code-image"></div>
              <b>使用支付宝打赏</b>
            </span>
            <span class="wechat-code">
              <div class="code-image"></div>
              <b>使用微信打赏</b>
            </span>
          </span>
        </div>
        <p class="notice">若你觉得我的文章对你有帮助，欢迎点击上方按钮对我打赏</p>
      </div>
    
    <!-- 打赏 END -->
    <!-- 二维码 START -->
    
      <div class="qrcode">
        <canvas id="share-qrcode"></canvas>
        <p class="notice">扫描二维码，分享此文章</p>
      </div>
    
    <!-- 二维码 END -->
    
      <!-- Utterances START -->
      <div id="utterances"></div>
      <script src="https://utteranc.es/client.js"
        repo="ltyeamin/blogtalks"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async></script>    
      <!-- Utterances END -->
    
  </article>
  <!-- Article END -->
  <!-- Catalog START -->
  
    <aside class="catalog-container">
  <div class="toc-main">
    <strong class="toc-title">Catalog</strong>
    
      <ol class="toc-nav"><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#1-AQS%E4%BB%8B%E7%BB%8D"><span class="toc-nav-text">1. AQS介绍</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#1-1-%E7%AE%80%E8%A6%81%E8%AF%B4%E6%98%8E"><span class="toc-nav-text">1.1 简要说明</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#1-2-%E7%BB%A7%E6%89%BF%E4%BD%93%E7%B3%BB"><span class="toc-nav-text">1.2 继承体系</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#1-2-1-%E7%BB%A7%E6%89%BF%E4%BD%93%E7%B3%BB%E5%9B%BE"><span class="toc-nav-text">1.2.1 继承体系图</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#1-2-2-AbstractOwnableSynchronizer%E9%A1%B6%E5%B1%82%E6%8A%BD%E8%B1%A1"><span class="toc-nav-text">1.2.2 AbstractOwnableSynchronizer顶层抽象</span></a></li></ol></li></ol></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#2-AQS%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90"><span class="toc-nav-text">2. AQS源码分析</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#2-1-%E6%88%90%E5%91%98%E5%8F%98%E9%87%8F"><span class="toc-nav-text">2.1 成员变量</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#2-2-%E9%9D%99%E6%80%81%E5%88%9D%E5%A7%8B%E5%8C%96"><span class="toc-nav-text">2.2 静态初始化</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#2-3-%E6%9E%84%E9%80%A0%E5%99%A8"><span class="toc-nav-text">2.3 构造器</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#2-4-%E9%87%8D%E8%A6%81%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4 重要方法</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-1-state%E7%9A%84getter-setter%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.1 state的getter&#x2F;setter方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-2-compareAndSetState%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.2 compareAndSetState方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-3-tryAcquire%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.3  tryAcquire方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-4-tryRelease%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.4 tryRelease方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-5-tryAcquireShared%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.5 tryAcquireShared方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-6-tryReleaseShared%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.6 tryReleaseShared方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-7-isHeldExclusively%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.7 isHeldExclusively方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-8-addWaiter%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.8  addWaiter方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-9-enq%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.9 enq方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-10-setHead%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.10 setHead方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-11-acquireQueued%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.11 acquireQueued方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-12-selfInterrupt%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.12 selfInterrupt方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-13-acquire%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.13 acquire方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-14-transferForSignal%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.14 transferForSignal方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-15-fullyRelease%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.15 fullyRelease方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-16-isOnSyncQueue%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.16 isOnSyncQueue方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-17-findNodeFromTail%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.17  findNodeFromTail方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-18-acquireInterruptibly%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.18  acquireInterruptibly方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-19-release%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.19 release方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-20-unparkSuccessor%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.20 unparkSuccessor方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-21-hasQueuedThreads%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.21 hasQueuedThreads方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-22-hasContended%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.22 hasContended方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-23-getFirstQueuedThread%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.23 getFirstQueuedThread方法</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#2-4-24-fullGetFirstQueuedThread%E6%96%B9%E6%B3%95"><span class="toc-nav-text">2.4.24 fullGetFirstQueuedThread方法</span></a></li></ol></li></ol></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#3-%E5%86%85%E9%83%A8%E7%B1%BB"><span class="toc-nav-text">3.内部类</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#3-1-%E7%AD%89%E5%BE%85%E9%98%9F%E5%88%97%E8%8A%82%E7%82%B9%E7%B1%BB"><span class="toc-nav-text">3.1 等待队列节点类</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#3-2-%E6%9D%A1%E4%BB%B6%E5%AF%B9%E8%B1%A1%E7%B1%BB"><span class="toc-nav-text">3.2 条件对象类</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#3-2-1-Condition%E9%A1%B6%E5%B1%82%E6%8E%A5%E5%8F%A3"><span class="toc-nav-text">3.2.1 Condition顶层接口</span></a></li><li class="toc-nav-item toc-nav-level-3"><a class="toc-nav-link" href="#3-2-2-ConditionObject%E7%B1%BB"><span class="toc-nav-text">3.2.2 ConditionObject类</span></a></li></ol></li></ol></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#4-AQS%E6%80%BB%E7%BB%93"><span class="toc-nav-text">4. AQS总结</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#4-1-AQS%E7%9A%84%E6%A0%B8%E5%BF%83%E6%80%9D%E6%83%B3%E4%B8%8E%E5%AE%9E%E7%8E%B0"><span class="toc-nav-text">4.1 AQS的核心思想与实现</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#4-2-%E6%A8%A1%E6%9D%BF%E6%96%B9%E6%B3%95%E7%9A%84%E6%8A%BD%E8%B1%A1"><span class="toc-nav-text">4.2 模板方法的抽象</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#5-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99"><span class="toc-nav-text">5.参考资料</span></a></li></ol>
    
  </div>
</aside>
  
  <!-- Catalog END -->
</main>

<script>
  (function () {
    var url = 'http://example.com/2020/07/22/【Java并发编程实战】-J.U.C并发包之AQS/';
    var banner = ''
    if (banner !== '' && banner !== 'undefined' && banner !== 'null') {
      $('#article-banner').css({
        'background-image': 'url(' + banner + ')'
      })
    } else {
      $('#article-banner').geopattern(url)
    }
    $('.header').removeClass('fixed-header')

    // error image
    $(".markdown-content img").on('error', function() {
      $(this).attr('src', '/css/images/error_icon.png')
      $(this).css({
        'cursor': 'default'
      })
    })

    // zoom image
    $(".markdown-content img").on('click', function() {
      var src = $(this).attr('src')
      if (src !== '/css/images/error_icon.png') {
        var imageW = $(this).width()
        var imageH = $(this).height()

        var zoom = ($(window).width() * 0.95 / imageW).toFixed(2)
        zoom = zoom < 1 ? 1 : zoom
        zoom = zoom > 2 ? 2 : zoom
        var transY = (($(window).height() - imageH) / 2).toFixed(2)

        $('body').append('<div class="image-view-wrap"><div class="image-view-inner"><img src="'+ src +'" /></div></div>')
        $('.image-view-wrap').addClass('wrap-active')
        $('.image-view-wrap img').css({
          'width': `${imageW}`,
          'transform': `translate3d(0, ${transY}px, 0) scale3d(${zoom}, ${zoom}, 1)`
        })
        $('html').css('overflow', 'hidden')

        $('.image-view-wrap').on('click', function() {
          $(this).remove()
          $('html').attr('style', '')
        })
      }
    })
  })();
</script>


  <script>
    var qr = new QRious({
      element: document.getElementById('share-qrcode'),
      value: document.location.href
    });
  </script>






    <div class="scroll-top">
  <span class="arrow-icon"></span>
</div>
    <footer class="app-footer">
  <p class="copyright">
    &copy; 2024 | Proudly powered by <a href="https://hexo.io" target="_blank">Hexo</a>
    <br>
    Theme by <a target="_blank" rel="noopener" href="https://github.com/ltyeamin">tong.li</a>
  </p>
</footer>

<script>
  function async(u, c) {
    var d = document, t = 'script',
      o = d.createElement(t),
      s = d.getElementsByTagName(t)[0];
    o.src = u;
    if (c) { o.addEventListener('load', function (e) { c(null, e); }, false); }
    s.parentNode.insertBefore(o, s);
  }
</script>
<script>
  async("https://cdn.staticfile.org/fastclick/1.0.6/fastclick.min.js", function(){
    FastClick.attach(document.body);
  })
</script>

<script>
  var hasLine = 'true';
  async("https://cdn.staticfile.org/highlight.js/9.12.0/highlight.min.js", function(){
    $('figure pre').each(function(i, block) {
      var figure = $(this).parents('figure');
      if (hasLine === 'false') {
        figure.find('.gutter').hide();
      }
      hljs.configure({useBR: true});
      var lang = figure.attr('class').split(' ')[1] || 'code';
      var codeHtml = $(this).html();
      var codeTag = document.createElement('code');
      codeTag.className = lang;
      codeTag.innerHTML = codeHtml;
      $(this).attr('class', '').empty().html(codeTag);
      figure.attr('data-lang', lang.toUpperCase());
      hljs.highlightBlock(block);
    });
  })
</script>
<!-- Baidu Tongji -->



<script src='https://cdn.staticfile.org/mermaid/8.11.2/mermaid.min.js'></script>



<script src="/js/script.js"></script>


  </body>
</html>